@phyzess/pappra 0.1.0-beta.13 → 0.1.0-beta.18
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 +134 -15
- package/assets/integrations/skills/pappra/SKILL.md +28 -7
- package/assets/integrations/skills/pappra/references/collaboration.md +633 -0
- package/assets/integrations/skills/pappra/references/environment.md +360 -0
- package/assets/integrations/skills/pappra/references/hosts.md +20 -0
- package/assets/integrations/skills/pappra/references/operations.md +36 -5
- package/dist/adapters/pi/recovery-extension.d.ts +65 -0
- package/dist/adapters/pi/recovery-extension.js +238 -0
- package/dist/adapters/pi/session-transition-extension.d.ts +30 -0
- package/dist/adapters/pi/session-transition-extension.js +265 -0
- package/dist/app/automatic-handoff-events.d.ts +26 -0
- package/dist/app/automatic-handoff-events.js +134 -0
- package/dist/app/bounded-file.d.ts +2 -0
- package/dist/app/bounded-file.js +2 -0
- package/dist/app/capability-evidence/claude.d.ts +37 -0
- package/dist/app/capability-evidence/claude.js +206 -0
- package/dist/app/capability-evidence/codex.d.ts +35 -0
- package/dist/app/capability-evidence/codex.js +193 -0
- package/dist/app/capability-evidence/index.d.ts +33 -0
- package/dist/app/capability-evidence/index.js +117 -0
- package/dist/app/capability-evidence/pi.d.ts +73 -0
- package/dist/app/capability-evidence/pi.js +669 -0
- package/dist/app/capability-evidence/shared.d.ts +69 -0
- package/dist/app/capability-evidence/shared.js +195 -0
- package/dist/app/collab-auto-handoff.d.ts +55 -0
- package/dist/app/collab-auto-handoff.js +384 -0
- package/dist/app/collab-bindings.d.ts +57 -0
- package/dist/app/collab-bindings.js +1006 -0
- package/dist/app/collab-bootstrap-transport.d.ts +163 -0
- package/dist/app/collab-bootstrap-transport.js +769 -0
- package/dist/app/collab-bootstrap.d.ts +137 -0
- package/dist/app/collab-bootstrap.js +3455 -0
- package/dist/app/collab-handoff.d.ts +12 -0
- package/dist/app/collab-handoff.js +511 -0
- package/dist/app/collab-messages.d.ts +2 -0
- package/dist/app/collab-messages.js +2 -0
- package/dist/app/collab-notify.d.ts +156 -0
- package/dist/app/collab-notify.js +1208 -0
- package/dist/app/collab-preflight.d.ts +34 -0
- package/dist/app/collab-preflight.js +96 -0
- package/dist/app/collab-recovery-executor.d.ts +161 -0
- package/dist/app/collab-recovery-executor.js +1153 -0
- package/dist/app/collab-recovery-projection.d.ts +103 -0
- package/dist/app/collab-recovery-projection.js +659 -0
- package/dist/app/collab-recovery.d.ts +25 -0
- package/dist/app/collab-recovery.js +429 -0
- package/dist/app/collab-resources.d.ts +16 -0
- package/dist/app/collab-resources.js +278 -0
- package/dist/app/collab-role-events.d.ts +22 -0
- package/dist/app/collab-role-events.js +329 -0
- package/dist/app/collab-role-orchestration.d.ts +53 -0
- package/dist/app/collab-role-orchestration.js +601 -0
- package/dist/app/collab-role-plan.d.ts +81 -0
- package/dist/app/collab-role-plan.js +504 -0
- package/dist/app/collab-role-repair.d.ts +109 -0
- package/dist/app/collab-role-repair.js +821 -0
- package/dist/app/collab-rollover.d.ts +263 -0
- package/dist/app/collab-rollover.js +1112 -0
- package/dist/app/collab-route.d.ts +64 -0
- package/dist/app/collab-route.js +240 -0
- package/dist/app/collab-session-transition.d.ts +221 -0
- package/dist/app/collab-session-transition.js +3334 -0
- package/dist/app/collab-state.d.ts +7 -0
- package/dist/app/collab-state.js +162 -0
- package/dist/app/collab-task-store.d.ts +22 -0
- package/dist/app/collab-task-store.js +204 -0
- package/dist/app/collab-work-execution.d.ts +127 -0
- package/dist/app/collab-work-execution.js +1027 -0
- package/dist/app/collab-work-plan.d.ts +87 -0
- package/dist/app/collab-work-plan.js +437 -0
- package/dist/app/collaboration.d.ts +8 -2
- package/dist/app/collaboration.js +101 -12
- package/dist/app/doctor.js +108 -5
- package/dist/app/host-mcp.js +34 -8
- package/dist/app/host-probe.js +4 -4
- package/dist/app/init.d.ts +58 -4
- package/dist/app/init.js +768 -155
- package/dist/app/managed-pi-bootstrap-admission.d.ts +14 -0
- package/dist/app/managed-pi-bootstrap-admission.js +104 -0
- package/dist/app/managed-pi-bootstrap-refresh.d.ts +10 -0
- package/dist/app/managed-pi-bootstrap-refresh.js +78 -0
- package/dist/app/managed-pi-delivery.d.ts +8 -0
- package/dist/app/managed-pi-delivery.js +110 -0
- package/dist/app/managed-pi-handoff-receiver.d.ts +15 -0
- package/dist/app/managed-pi-handoff-receiver.js +263 -0
- package/dist/app/managed-pi-handoff-reference.d.ts +3 -0
- package/dist/app/managed-pi-handoff-reference.js +60 -0
- package/dist/app/managed-pi-herdr.d.ts +21 -0
- package/dist/app/managed-pi-herdr.js +185 -0
- package/dist/app/managed-pi-initial-admission.d.ts +28 -0
- package/dist/app/managed-pi-initial-admission.js +416 -0
- package/dist/app/managed-pi-initial-launch.d.ts +5 -0
- package/dist/app/managed-pi-initial-launch.js +61 -0
- package/dist/app/managed-pi-native-observation.d.ts +36 -0
- package/dist/app/managed-pi-native-observation.js +191 -0
- package/dist/app/managed-pi-readiness.d.ts +29 -0
- package/dist/app/managed-pi-readiness.js +288 -0
- package/dist/app/managed-pi-repair-stop.d.ts +21 -0
- package/dist/app/managed-pi-repair-stop.js +371 -0
- package/dist/app/managed-pi-resume-admission.d.ts +32 -0
- package/dist/app/managed-pi-resume-admission.js +618 -0
- package/dist/app/managed-pi-retirement.d.ts +28 -0
- package/dist/app/managed-pi-retirement.js +112 -0
- package/dist/app/managed-pi-sdk-control.d.ts +7 -0
- package/dist/app/managed-pi-sdk-control.js +169 -0
- package/dist/app/managed-pi-sdk-runtime.d.ts +3 -0
- package/dist/app/managed-pi-sdk-runtime.js +483 -0
- package/dist/app/managed-pi-source-admission.d.ts +14 -0
- package/dist/app/managed-pi-source-admission.js +323 -0
- package/dist/app/managed-pi-transition-host.d.ts +36 -0
- package/dist/app/managed-pi-transition-host.js +292 -0
- package/dist/app/managed-pi.d.ts +54 -0
- package/dist/app/managed-pi.js +248 -0
- package/dist/app/shell-readiness.d.ts +66 -0
- package/dist/app/shell-readiness.js +368 -0
- package/dist/app/task-pin.d.ts +2 -23
- package/dist/app/task-pin.js +2 -113
- package/dist/cli/commands/collaboration-binding.d.ts +13 -0
- package/dist/cli/commands/collaboration-binding.js +118 -0
- package/dist/cli/commands/collaboration-bootstrap.d.ts +10 -0
- package/dist/cli/commands/collaboration-bootstrap.js +84 -0
- package/dist/cli/commands/collaboration-capabilities.d.ts +13 -0
- package/dist/cli/commands/collaboration-capabilities.js +127 -0
- package/dist/cli/commands/collaboration-handoff.d.ts +13 -0
- package/dist/cli/commands/collaboration-handoff.js +102 -0
- package/dist/cli/commands/collaboration-message.d.ts +17 -0
- package/dist/cli/commands/collaboration-message.js +177 -0
- package/dist/cli/commands/collaboration-plan.d.ts +8 -0
- package/dist/cli/commands/collaboration-plan.js +108 -0
- package/dist/cli/commands/collaboration-preflight.d.ts +10 -0
- package/dist/cli/commands/collaboration-preflight.js +167 -0
- package/dist/cli/commands/collaboration-recovery-run.d.ts +46 -0
- package/dist/cli/commands/collaboration-recovery-run.js +224 -0
- package/dist/cli/commands/collaboration-recovery.d.ts +11 -0
- package/dist/cli/commands/collaboration-recovery.js +104 -0
- package/dist/cli/commands/collaboration-resources.d.ts +11 -0
- package/dist/cli/commands/collaboration-resources.js +96 -0
- package/dist/cli/commands/collaboration-role-plan.d.ts +9 -0
- package/dist/cli/commands/collaboration-role-plan.js +69 -0
- package/dist/cli/commands/collaboration-role-run.d.ts +11 -0
- package/dist/cli/commands/collaboration-role-run.js +128 -0
- package/dist/cli/commands/collaboration-rollover.d.ts +10 -0
- package/dist/cli/commands/collaboration-rollover.js +103 -0
- package/dist/cli/commands/collaboration-state.d.ts +10 -0
- package/dist/cli/commands/collaboration-state.js +96 -0
- package/dist/cli/commands/collaboration-transition.d.ts +10 -0
- package/dist/cli/commands/collaboration-transition.js +75 -0
- package/dist/cli/commands/collaboration-work-run.d.ts +34 -0
- package/dist/cli/commands/collaboration-work-run.js +178 -0
- package/dist/cli/commands/collaboration.d.ts +4 -0
- package/dist/cli/commands/collaboration.js +39 -4
- package/dist/cli/commands/continuity.js +2 -6
- package/dist/cli/commands/docs.d.ts +2 -0
- package/dist/cli/commands/docs.js +89 -15
- package/dist/cli/commands/host.d.ts +7 -1
- package/dist/cli/commands/host.js +122 -7
- package/dist/cli/commands/init.d.ts +20 -3
- package/dist/cli/commands/init.js +897 -232
- package/dist/cli/commands/mcp.d.ts +1 -0
- package/dist/cli/commands/mcp.js +11 -5
- package/dist/cli/commands/repair.d.ts +12 -0
- package/dist/cli/commands/repair.js +41 -0
- package/dist/cli/commands/runtime.d.ts +1 -1
- package/dist/cli/commands/runtime.js +139 -38
- package/dist/cli/commands/session.d.ts +7 -0
- package/dist/cli/commands/session.js +82 -0
- package/dist/cli/commands/task.js +19 -5
- package/dist/cli/run.js +866 -24
- package/dist/code/identity.d.ts +7 -0
- package/dist/code/identity.js +7 -3
- package/dist/code/registration.js +7 -0
- package/dist/code/service.d.ts +9 -0
- package/dist/code/service.js +16 -3
- package/dist/code/text.js +19 -7
- package/dist/collab/admission.d.ts +91 -66
- package/dist/collab/admission.js +21 -6
- package/dist/collab/canonical.d.ts +1 -1
- package/dist/collab/canonical.js +44 -3
- package/dist/collab/envelope.d.ts +2 -2
- package/dist/collab/envelope.js +12 -12
- package/dist/collab/first-work.d.ts +3 -0
- package/dist/collab/first-work.js +15 -0
- package/dist/collab/handoff.d.ts +16 -0
- package/dist/collab/handoff.js +39 -5
- package/dist/collab/index.d.ts +97 -1
- package/dist/collab/index.js +9 -1
- package/dist/collab/messages.js +126 -3
- package/dist/collab/persisted-messages.d.ts +123 -0
- package/dist/collab/persisted-messages.js +496 -0
- package/dist/collab/preflight.d.ts +1 -1
- package/dist/collab/resources.d.ts +13 -3
- package/dist/collab/resources.js +37 -6
- package/dist/collab/rollover.d.ts +311 -0
- package/dist/collab/rollover.js +1024 -0
- package/dist/collab/store.d.ts +1 -0
- package/dist/collab/store.js +1 -4
- package/dist/collab/types.d.ts +2 -354
- package/dist/collab/validation.d.ts +2 -10
- package/dist/collab/validation.js +2 -303
- package/dist/collab/work-plan.d.ts +105 -0
- package/dist/collab/work-plan.js +843 -0
- package/dist/continuity/context.d.ts +11 -2
- package/dist/continuity/context.js +100 -13
- package/dist/continuity/handoff-bundle.d.ts +296 -0
- package/dist/continuity/handoff-bundle.js +477 -0
- package/dist/continuity/index.d.ts +2 -0
- package/dist/continuity/index.js +1 -0
- package/dist/continuity/paths.js +10 -2
- package/dist/continuity/service.js +91 -15
- package/dist/continuity/task-pin.d.ts +24 -0
- package/dist/continuity/task-pin.js +590 -0
- package/dist/doctor.d.ts +1 -0
- package/dist/doctor.js +6 -0
- package/dist/experimental/index.d.ts +13 -0
- package/dist/experimental/index.js +25 -0
- package/dist/experimental/pi.d.ts +4 -0
- package/dist/experimental/pi.js +12 -0
- package/dist/hosts/claude/native.js +1 -1
- package/dist/hosts/codex/native.js +1 -1
- package/dist/hosts/codex/protocol.js +1 -1
- package/dist/hosts/integration/bootstrap-config.d.ts +58 -0
- package/dist/hosts/integration/bootstrap-config.js +254 -0
- package/dist/hosts/integration/bundle-export.d.ts +44 -0
- package/dist/hosts/integration/bundle-export.js +366 -3
- package/dist/hosts/integration/bundle.js +3 -0
- package/dist/hosts/integration/hook.js +36 -9
- package/dist/hosts/integration/pappra-bootstrap-extension.mjs +80 -0
- package/dist/hosts/integration/pappra-extension-runtime.mjs +59 -24631
- package/dist/hosts/integration/pappra-hook.mjs +61 -24749
- package/dist/hosts/integration/pappra-recovery-extension.mjs +259 -0
- package/dist/hosts/integration/pappra-session-transition-extension.mjs +276 -0
- package/dist/hosts/integration/pi-bootstrap-extension.d.ts +36 -0
- package/dist/hosts/integration/pi-bootstrap-extension.js +101 -0
- package/dist/hosts/integration/pi-bootstrap-guard.d.ts +125 -0
- package/dist/hosts/integration/pi-bootstrap-guard.js +438 -0
- package/dist/hosts/integration/pi-bootstrap-runtime.d.ts +63 -0
- package/dist/hosts/integration/pi-bootstrap-runtime.js +223 -0
- package/dist/hosts/integration/pi-native-events.d.ts +112 -0
- package/dist/hosts/integration/pi-native-events.js +348 -0
- package/dist/hosts/integration/pi-rollover-extension.d.ts +166 -0
- package/dist/hosts/integration/pi-rollover-extension.js +431 -0
- package/dist/hosts/integration/recovery-config.d.ts +48 -0
- package/dist/hosts/integration/recovery-config.js +117 -0
- package/dist/hosts/integration/service.d.ts +6 -1
- package/dist/hosts/integration/service.js +485 -35
- package/dist/hosts/integration/support.d.ts +7 -0
- package/dist/hosts/integration/support.js +9 -1
- package/dist/hosts/integration/templates.d.ts +3 -0
- package/dist/hosts/integration/templates.js +26 -3
- package/dist/hosts/pi/managed-host-identity.d.ts +2 -0
- package/dist/hosts/pi/managed-host-identity.js +40 -0
- package/dist/hosts/pi/managed-provider-diagnostics.d.ts +6 -0
- package/dist/hosts/pi/managed-provider-diagnostics.js +184 -0
- package/dist/hosts/pi/managed-sdk-session.d.ts +335 -0
- package/dist/hosts/pi/managed-sdk-session.js +1639 -0
- package/dist/hosts/pi/managed-session-extension.d.ts +20 -0
- package/dist/hosts/pi/managed-session-extension.js +84 -0
- package/dist/hosts/pi/managed-session.d.ts +177 -0
- package/dist/hosts/pi/managed-session.js +1557 -0
- package/dist/hosts/pi/protocol.js +1 -1
- package/dist/hosts/pi/query-result.js +1 -1
- package/dist/hosts/pi/resume-capability.d.ts +41 -0
- package/dist/hosts/pi/resume-capability.js +33 -0
- package/dist/hosts/pi/rpc.d.ts +182 -134
- package/dist/hosts/pi/rpc.js +230 -37
- package/dist/hosts/pilot.d.ts +97 -74
- package/dist/hosts/pilot.js +5 -1
- package/dist/hosts/version.d.ts +3 -0
- package/dist/hosts/version.js +18 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/infra/bounded-file.d.ts +19 -0
- package/dist/infra/bounded-file.js +66 -0
- package/dist/infra/fs.js +10 -2
- package/dist/infra/git.d.ts +29 -0
- package/dist/infra/git.js +45 -9
- package/dist/infra/json-property.d.ts +2 -0
- package/dist/infra/json-property.js +69 -0
- package/dist/infra/json.d.ts +4 -0
- package/dist/infra/json.js +24 -0
- package/dist/infra/owned-process-group.js +1 -1
- package/dist/infra/private-lock.d.ts +16 -0
- package/dist/infra/private-lock.js +148 -0
- package/dist/infra/private-state.d.ts +7 -0
- package/dist/infra/private-state.js +146 -0
- package/dist/infra/process-identity.d.ts +12 -0
- package/dist/infra/process-identity.js +142 -0
- package/dist/infra/validation.d.ts +5 -0
- package/dist/infra/validation.js +15 -0
- package/dist/init.d.ts +1 -0
- package/dist/init.js +6 -0
- package/dist/install/apply.d.ts +9 -1
- package/dist/install/apply.js +176 -12
- package/dist/install/dependencies.d.ts +38 -0
- package/dist/install/dependencies.js +282 -0
- package/dist/install/ownership.js +30 -1
- package/dist/install/references.d.ts +31 -0
- package/dist/install/references.js +208 -0
- package/dist/install/repair.d.ts +37 -0
- package/dist/install/repair.js +798 -0
- package/dist/install/reset-local.d.ts +16 -0
- package/dist/install/reset-local.js +304 -0
- package/dist/install/rollback.d.ts +3 -0
- package/dist/install/rollback.js +9 -3
- package/dist/install/runtime.d.ts +10 -6
- package/dist/install/runtime.js +299 -59
- package/dist/install/source-fingerprint.d.ts +2 -0
- package/dist/install/source-fingerprint.js +103 -0
- package/dist/knowledge/catalog.d.ts +1 -0
- package/dist/knowledge/catalog.js +143 -10
- package/dist/knowledge/journal.js +17 -7
- package/dist/knowledge/paths.js +2 -1
- package/dist/knowledge/refs.js +4 -0
- package/dist/knowledge/register-batch.d.ts +4 -0
- package/dist/knowledge/register-batch.js +225 -0
- package/dist/knowledge/relocate.d.ts +5 -0
- package/dist/knowledge/relocate.js +92 -0
- package/dist/knowledge/scan.js +103 -47
- package/dist/knowledge/service.d.ts +3 -0
- package/dist/knowledge/service.js +33 -1
- package/dist/knowledge/write.d.ts +4 -1
- package/dist/knowledge/write.js +1 -1
- package/dist/mcp/server.d.ts +4 -2
- package/dist/mcp/server.js +87 -136
- package/dist/schemas/collaboration-state-validation.d.ts +6 -0
- package/dist/schemas/collaboration-state-validation.js +342 -0
- package/dist/schemas/collaboration-state.d.ts +436 -0
- package/dist/schemas/collaboration-state.js +1 -0
- package/dist/schemas/collaboration.d.ts +335 -0
- package/dist/schemas/collaboration.js +272 -0
- package/dist/schemas/continuity.d.ts +8 -0
- package/dist/schemas/continuity.js +13 -3
- package/dist/schemas/doctor.d.ts +1 -0
- package/dist/schemas/doctor.js +1 -0
- package/dist/schemas/document.d.ts +61 -0
- package/dist/schemas/document.js +9 -0
- package/dist/schemas/errors.d.ts +1 -0
- package/dist/schemas/errors.js +1 -0
- package/dist/schemas/host.d.ts +24 -0
- package/dist/schemas/host.js +19 -0
- package/dist/schemas/install.d.ts +8 -2
- package/dist/schemas/install.js +11 -1
- package/dist/schemas/managed-pi-execution.d.ts +16 -0
- package/dist/schemas/managed-pi-execution.js +2 -0
- package/dist/schemas/outcome.d.ts +9 -5
- package/dist/workspace/config-file.js +1 -3
- package/dist/workspace/documents.js +12 -2
- package/dist/workspace/repositories.d.ts +7 -0
- package/dist/workspace/repositories.js +14 -5
- package/package.json +35 -35
- package/skills/pappra/SKILL.md +28 -7
- package/skills/pappra/references/collaboration.md +633 -0
- package/skills/pappra/references/environment.md +360 -0
- package/skills/pappra/references/hosts.md +20 -0
- package/skills/pappra/references/operations.md +36 -5
- package/dist/app/collab-from.d.ts +0 -35
- package/dist/app/collab-from.js +0 -84
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { readBoundedFile } from '../../app/bounded-file.js';
|
|
3
|
+
import { COLLAB_WORK_EXECUTION_SCHEMA, runWorkExecution, } from '../../app/collab-work-execution.js';
|
|
4
|
+
const MAX_REQUEST_BYTES = 64 * 1024;
|
|
5
|
+
export const collaborationWorkRunUsage = 'pappra collab work-run --request <abs work-execution.json> [--apply] [--json]\n\n' +
|
|
6
|
+
'Without --apply this is a zero-write, zero-notification plan. Apply revalidates the\n' +
|
|
7
|
+
'pinned work plan, current assignments, capability cards, coordinator epoch, resource\n' +
|
|
8
|
+
'claims and visible participant binding; it records a durable per-node intent before\n' +
|
|
9
|
+
'one bounded concurrent notification batch. Existing/unknown intents are reconciliation\n' +
|
|
10
|
+
'only and are never automatically replayed. This command never launches sessions, merges\n' +
|
|
11
|
+
'code or accepts a report.';
|
|
12
|
+
export function parseCollaborationWorkRunArgs(argv) {
|
|
13
|
+
const errors = [];
|
|
14
|
+
let requestFile = null;
|
|
15
|
+
let apply = false;
|
|
16
|
+
let json = false;
|
|
17
|
+
let sawApply = false;
|
|
18
|
+
let sawJson = false;
|
|
19
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
20
|
+
const arg = argv[index];
|
|
21
|
+
if (arg === '--request') {
|
|
22
|
+
if (requestFile !== null)
|
|
23
|
+
errors.push('--request may be given only once.');
|
|
24
|
+
const value = argv[index + 1];
|
|
25
|
+
if (value === undefined || value.startsWith('--'))
|
|
26
|
+
errors.push('--request requires a value.');
|
|
27
|
+
else {
|
|
28
|
+
requestFile = value;
|
|
29
|
+
index += 1;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else if (arg === '--apply') {
|
|
33
|
+
if (sawApply)
|
|
34
|
+
errors.push('--apply may be given only once.');
|
|
35
|
+
sawApply = true;
|
|
36
|
+
apply = true;
|
|
37
|
+
}
|
|
38
|
+
else if (arg === '--json') {
|
|
39
|
+
if (sawJson)
|
|
40
|
+
errors.push('--json may be given only once.');
|
|
41
|
+
sawJson = true;
|
|
42
|
+
json = true;
|
|
43
|
+
}
|
|
44
|
+
else
|
|
45
|
+
errors.push(`unknown option: ${String(arg)}`);
|
|
46
|
+
}
|
|
47
|
+
return { options: { requestFile, apply, json }, errors };
|
|
48
|
+
}
|
|
49
|
+
function isObject(value) {
|
|
50
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
51
|
+
}
|
|
52
|
+
function isAbsolute(value) {
|
|
53
|
+
return typeof value === 'string' && path.isAbsolute(value);
|
|
54
|
+
}
|
|
55
|
+
function loadRequest(file) {
|
|
56
|
+
const read = readBoundedFile(file, MAX_REQUEST_BYTES);
|
|
57
|
+
if (!read.ok)
|
|
58
|
+
return { ok: false, error: `request_file_${read.code}` };
|
|
59
|
+
let parsed;
|
|
60
|
+
try {
|
|
61
|
+
parsed = JSON.parse(read.text);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return { ok: false, error: 'request_file_invalid_json' };
|
|
65
|
+
}
|
|
66
|
+
if (!isObject(parsed) ||
|
|
67
|
+
parsed.schema !== 'pappra/collab-work-execution-request/1')
|
|
68
|
+
return { ok: false, error: 'request_schema_invalid' };
|
|
69
|
+
const keys = Object.keys(parsed).sort();
|
|
70
|
+
const expected = [
|
|
71
|
+
'binding_file',
|
|
72
|
+
'caller',
|
|
73
|
+
'caller_pane',
|
|
74
|
+
'capability_cards',
|
|
75
|
+
'plan_file',
|
|
76
|
+
'schema',
|
|
77
|
+
'task_root',
|
|
78
|
+
];
|
|
79
|
+
const expectedOptional = [...expected, 'max_concurrency'].sort();
|
|
80
|
+
if (keys.join('|') !== expected.sort().join('|') &&
|
|
81
|
+
keys.join('|') !== expectedOptional.join('|'))
|
|
82
|
+
return { ok: false, error: 'request_fields_invalid' };
|
|
83
|
+
if (!isAbsolute(parsed.task_root) ||
|
|
84
|
+
!isAbsolute(parsed.plan_file) ||
|
|
85
|
+
!isAbsolute(parsed.binding_file))
|
|
86
|
+
return { ok: false, error: 'request_paths_must_be_absolute' };
|
|
87
|
+
if (typeof parsed.caller_pane !== 'string' ||
|
|
88
|
+
!/^[A-Za-z0-9]+:p[A-Za-z0-9]+$/.test(parsed.caller_pane))
|
|
89
|
+
return { ok: false, error: 'caller_pane_invalid' };
|
|
90
|
+
if (!isObject(parsed.caller) ||
|
|
91
|
+
Object.keys(parsed.caller).sort().join('|') !==
|
|
92
|
+
'agent_id|cwd|harness|session_id' ||
|
|
93
|
+
typeof parsed.caller.agent_id !== 'string' ||
|
|
94
|
+
typeof parsed.caller.session_id !== 'string' ||
|
|
95
|
+
typeof parsed.caller.harness !== 'string' ||
|
|
96
|
+
!isAbsolute(parsed.caller.cwd))
|
|
97
|
+
return { ok: false, error: 'caller_identity_invalid' };
|
|
98
|
+
if (!Array.isArray(parsed.capability_cards) ||
|
|
99
|
+
parsed.capability_cards.length > 64)
|
|
100
|
+
return { ok: false, error: 'capability_cards_invalid' };
|
|
101
|
+
const assignmentIds = new Set();
|
|
102
|
+
const cards = [];
|
|
103
|
+
for (const item of parsed.capability_cards) {
|
|
104
|
+
if (!isObject(item) ||
|
|
105
|
+
Object.keys(item).sort().join('|') !==
|
|
106
|
+
'assignment_id|capabilities_file' ||
|
|
107
|
+
typeof item.assignment_id !== 'string' ||
|
|
108
|
+
!isAbsolute(item.capabilities_file) ||
|
|
109
|
+
assignmentIds.has(item.assignment_id))
|
|
110
|
+
return { ok: false, error: 'capability_cards_invalid' };
|
|
111
|
+
assignmentIds.add(item.assignment_id);
|
|
112
|
+
cards.push({
|
|
113
|
+
assignment_id: item.assignment_id,
|
|
114
|
+
capabilities_file: item.capabilities_file,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const maxConcurrency = parsed.max_concurrency;
|
|
118
|
+
if (maxConcurrency !== undefined &&
|
|
119
|
+
(typeof maxConcurrency !== 'number' ||
|
|
120
|
+
!Number.isSafeInteger(maxConcurrency) ||
|
|
121
|
+
maxConcurrency < 1 ||
|
|
122
|
+
maxConcurrency > 8))
|
|
123
|
+
return { ok: false, error: 'max_concurrency_invalid' };
|
|
124
|
+
return {
|
|
125
|
+
ok: true,
|
|
126
|
+
value: {
|
|
127
|
+
task_root: parsed.task_root,
|
|
128
|
+
plan_file: parsed.plan_file,
|
|
129
|
+
binding_file: parsed.binding_file,
|
|
130
|
+
caller: parsed.caller,
|
|
131
|
+
caller_pane: parsed.caller_pane,
|
|
132
|
+
capability_cards: cards,
|
|
133
|
+
...(maxConcurrency === undefined
|
|
134
|
+
? {}
|
|
135
|
+
: { max_concurrency: maxConcurrency }),
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function invalid(output, options, errors) {
|
|
140
|
+
if (options.json)
|
|
141
|
+
output.stdout(`${JSON.stringify({ schema: COLLAB_WORK_EXECUTION_SCHEMA, ok: false, status: 'invalid', errors })}\n`);
|
|
142
|
+
else {
|
|
143
|
+
output.stdout('Work execution request invalid.\n');
|
|
144
|
+
for (const error of errors)
|
|
145
|
+
output.stdout(` - ${error}\n`);
|
|
146
|
+
output.stdout(`\n${collaborationWorkRunUsage}\n`);
|
|
147
|
+
}
|
|
148
|
+
return 2;
|
|
149
|
+
}
|
|
150
|
+
function emitHuman(report, output) {
|
|
151
|
+
output.stdout(`Work execution ${report.apply ? 'apply' : 'plan'}: ${report.status}${report.task_id ? ` (${report.task_id})` : ''}.\n`);
|
|
152
|
+
output.stdout(` nodes ${report.nodes.length}, concurrent limit ${report.concurrency.limit}, actual overlap ${report.concurrency.actual_overlap ? 'yes' : 'no'}\n`);
|
|
153
|
+
for (const node of report.nodes) {
|
|
154
|
+
output.stdout(` ${node.role} ${node.node_id} (${node.assignment_id}#${node.attempt}): ${node.execution_status}; acceptance ${node.acceptance}\n`);
|
|
155
|
+
for (const blocker of node.blockers)
|
|
156
|
+
output.stdout(` - ${blocker}\n`);
|
|
157
|
+
if (node.intent_message_id)
|
|
158
|
+
output.stdout(` intent: ${node.intent_message_id}\n`);
|
|
159
|
+
}
|
|
160
|
+
output.stdout(` immutable report pointers: ${report.reports.length}; no merge or acceptance performed\n`);
|
|
161
|
+
}
|
|
162
|
+
export async function runCollaborationWorkRunCommand(options, output, deps = {}) {
|
|
163
|
+
if (options.requestFile === null)
|
|
164
|
+
return invalid(output, options, ['--request is required.']);
|
|
165
|
+
if (!path.isAbsolute(options.requestFile))
|
|
166
|
+
return invalid(output, options, ['--request must be absolute.']);
|
|
167
|
+
const request = loadRequest(options.requestFile);
|
|
168
|
+
if (!request.ok)
|
|
169
|
+
return invalid(output, options, [request.error]);
|
|
170
|
+
const report = await runWorkExecution({ request: request.value, apply: options.apply }, deps);
|
|
171
|
+
if (options.json)
|
|
172
|
+
output.stdout(`${JSON.stringify(report)}\n`);
|
|
173
|
+
else
|
|
174
|
+
emitHuman(report, output);
|
|
175
|
+
if (report.status === 'planned' || report.status === 'applied')
|
|
176
|
+
return 0;
|
|
177
|
+
return report.status === 'invalid' ? 2 : 1;
|
|
178
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { CliOutput } from '../output.js';
|
|
2
|
+
/** One source of truth for the full collaboration command family in help output. */
|
|
3
|
+
export declare const collaborationCommandLine = "pappra collab <prepare|run|work-run|role-run|query|preflight|plan|role-plan|bootstrap|rollover|transition|message|capabilities|state|resource|handoff|recovery|recovery-run|binding> [options]";
|
|
2
4
|
export declare const collaborationUsage: string;
|
|
3
5
|
export interface CollaborationCommandOptions {
|
|
4
6
|
readonly cwd: string;
|
|
@@ -9,5 +11,7 @@ export interface CollaborationCommandOptions {
|
|
|
9
11
|
readonly capabilitiesFile: string | null;
|
|
10
12
|
readonly controller: string | null;
|
|
11
13
|
readonly domainRoot: string | null;
|
|
14
|
+
readonly rpcRequestTimeoutMs?: number;
|
|
15
|
+
readonly rpcOperationTimeoutMs?: number;
|
|
12
16
|
}
|
|
13
17
|
export declare function runCollaborationCommand(options: CollaborationCommandOptions, output: CliOutput, input?: NodeJS.ReadableStream): Promise<number>;
|
|
@@ -1,10 +1,38 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { FixtureController, PiRpcController, driveRun, inspectPreparedHistory, prepareCollaboration, startPrepared, } from '../../app/collaboration.js';
|
|
4
|
-
|
|
4
|
+
/** One source of truth for the full collaboration command family in help output. */
|
|
5
|
+
export const collaborationCommandLine = 'pappra collab <prepare|run|work-run|role-run|query|preflight|plan|role-plan|bootstrap|rollover|transition|message|capabilities|state|resource|handoff|recovery|recovery-run|binding> [options]';
|
|
6
|
+
export const collaborationUsage = `${collaborationCommandLine}\n` +
|
|
5
7
|
' prepare --goal <file> --domain-root <dir> [--json]\n' +
|
|
6
8
|
' run --prepared <file> --capabilities <card> --controller <fixture|pi-rpc>\n' +
|
|
9
|
+
' [--rpc-request-timeout-ms <1..60000>] [--rpc-operation-timeout-ms <1..86400000>]\n' +
|
|
10
|
+
' work-run --request <abs work-execution.json> [--apply] [--json]\n' +
|
|
11
|
+
' role-run --request <abs role-orchestration.json> [--apply] [--json]\n' +
|
|
12
|
+
' Apply records bounded notification intents; plans write and notify nothing.\n' +
|
|
7
13
|
' query --prepared <file> [--json]\n' +
|
|
14
|
+
' preflight --assignment <file> --capabilities <card> [--max-age-minutes <n>] [--json]\n' +
|
|
15
|
+
' plan --task-root <dir> --config <plan.json> [--json]\n' +
|
|
16
|
+
' role-plan expand --request <abs role-plan.json> [--json]\n' +
|
|
17
|
+
' role-plan aggregate --request <abs role-plan.json> --task-root <abs> --config <abs expanded-plan.json> [--json]\n' +
|
|
18
|
+
' rollover <inspect|plan> --task-root <dir> --request <request.json> [--json]\n' +
|
|
19
|
+
' bootstrap <plan|apply> --task-root <abs> --request <abs request.json> [--json]\n' +
|
|
20
|
+
' Plan is read-only; apply launches only a visible Pi sibling or verified task-bound reuse.\n' +
|
|
21
|
+
' Unknown effects are reconciled, not retried; submission is not acceptance.\n' +
|
|
22
|
+
' Rollover remains read-only: no apply, native stop proof, route removal or session archive.\n' +
|
|
23
|
+
' transition <plan|apply> --task-root <abs> --request <abs request.json> [--json]\n' +
|
|
24
|
+
' Pre-transfer apply requires the opt-in Pi host; first-work and retirement resume from CLI.\n' +
|
|
25
|
+
' Unsupported native-quiescence proof blocks before successor launch or claim transfer.\n' +
|
|
26
|
+
' Applied ACK and REPORT pointers are required; retirement retains the original transcript.\n' +
|
|
27
|
+
' message <send|list|read|notify> --task-root <dir> [options]\n' +
|
|
28
|
+
' capabilities derive --harness <pi|codex|claude> --assignment <file> --template <file> [--execution <file> | --live] [--session <file> | --events <file>] [--json]\n' +
|
|
29
|
+
' state <show|doctor|epoch-check> --task-root <dir> [options]\n' +
|
|
30
|
+
' resource <list|claim|release> --task-root <dir> [options]\n' +
|
|
31
|
+
' handoff <inventory|begin|stopped|rebind|transfer|confirm|complete|abort|release-dispatch> --task-root <dir> [options]\n' +
|
|
32
|
+
' recovery <inspect|reconcile|lock-break> --task-root <dir> [options]\n' +
|
|
33
|
+
' recovery-run --request <abs recovery-run.json> [--apply] [--json]\n' +
|
|
34
|
+
' Apply requires exact session/cwd/harness/pane and a task-local digest-pinned binding.\n' +
|
|
35
|
+
' binding <list|resolve|bind|unbind> [--root <dir>] [options]\n' +
|
|
8
36
|
' run reads pappra/collaboration-command/1 JSONL from stdin and writes\n' +
|
|
9
37
|
' pappra/collaboration-event/1 JSONL to stdout.';
|
|
10
38
|
function failure(code, message) {
|
|
@@ -17,11 +45,18 @@ function readGoal(file) {
|
|
|
17
45
|
}
|
|
18
46
|
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
19
47
|
}
|
|
20
|
-
function controllerFor(name) {
|
|
48
|
+
function controllerFor(name, options) {
|
|
21
49
|
if (name === 'fixture')
|
|
22
50
|
return new FixtureController();
|
|
23
51
|
if (name === 'pi-rpc')
|
|
24
|
-
return new PiRpcController(
|
|
52
|
+
return new PiRpcController({
|
|
53
|
+
...(options.rpcRequestTimeoutMs === undefined
|
|
54
|
+
? {}
|
|
55
|
+
: { requestTimeoutMs: options.rpcRequestTimeoutMs }),
|
|
56
|
+
...(options.rpcOperationTimeoutMs === undefined
|
|
57
|
+
? {}
|
|
58
|
+
: { operationTimeoutMs: options.rpcOperationTimeoutMs }),
|
|
59
|
+
});
|
|
25
60
|
return null;
|
|
26
61
|
}
|
|
27
62
|
const MAX_COMMAND_LINE_BYTES = 256 * 1024;
|
|
@@ -145,7 +180,7 @@ export async function runCollaborationCommand(options, output, input = process.s
|
|
|
145
180
|
output.stderr('pappra: collab run requires --prepared <file> and --capabilities <card>\n');
|
|
146
181
|
return 2;
|
|
147
182
|
}
|
|
148
|
-
const controller = controllerFor(options.controller);
|
|
183
|
+
const controller = controllerFor(options.controller, options);
|
|
149
184
|
if (controller === null) {
|
|
150
185
|
output.stderr('pappra: collab run requires --controller <fixture|pi-rpc>\n');
|
|
151
186
|
return 2;
|
|
@@ -124,10 +124,6 @@ export async function runResumeCommand(options, output) {
|
|
|
124
124
|
else {
|
|
125
125
|
printDiagnostics(output, result.diagnostics);
|
|
126
126
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
result.packet.executionAllowed &&
|
|
130
|
-
result.packet.verificationStatus === 'current'
|
|
131
|
-
? 0
|
|
132
|
-
: 1;
|
|
127
|
+
// Reading advisory handoff context does not acquire execution authority.
|
|
128
|
+
return result.ok && result.packet?.verificationStatus === 'current' ? 0 : 1;
|
|
133
129
|
}
|
|
@@ -4,6 +4,8 @@ export interface DocsCommandOptions {
|
|
|
4
4
|
readonly cwd: string;
|
|
5
5
|
readonly action: string | null;
|
|
6
6
|
readonly argument: string | null;
|
|
7
|
+
readonly targetPath?: string | null;
|
|
8
|
+
readonly scope?: string | null;
|
|
7
9
|
readonly json: boolean;
|
|
8
10
|
readonly includePrivate: boolean;
|
|
9
11
|
readonly includeArchived: boolean;
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { resolveWorkspaceRoot } from '../../workspace/resolve.js';
|
|
2
2
|
import { scanDiscoveredDocuments } from '../../knowledge/scan.js';
|
|
3
3
|
import { formatDiagnostic } from '../../schemas/diagnostics.js';
|
|
4
|
-
import { docsArchiveReportSchema, docsCheckReportSchema, docsListReportSchema, } from '../../schemas/document.js';
|
|
4
|
+
import { docsArchiveReportSchema, docsCheckReportSchema, docsListReportSchema, documentLocationSchema, } from '../../schemas/document.js';
|
|
5
5
|
import { KnowledgeService, } from '../../knowledge/index.js';
|
|
6
|
-
export const docsUsage = 'pappra docs <list|check|archive|scan> [options]\n' +
|
|
6
|
+
export const docsUsage = 'pappra docs <list|check|archive|scan|relocate|forget> [options]\n' +
|
|
7
7
|
' list [--include-private] [--include-archived] [--json]\n' +
|
|
8
8
|
' check [--include-private] [--json]\n' +
|
|
9
9
|
' archive <documentId> [--json]\n' +
|
|
10
10
|
' scan [--apply] [--json]\n\n' +
|
|
11
|
-
'
|
|
12
|
-
'
|
|
11
|
+
' relocate <documentId> <workspace-relative-path> [--apply] [--json]\n' +
|
|
12
|
+
' forget <documentId> [--scope private|shared] [--apply] [--json]\n\n' +
|
|
13
|
+
'scan registers existing documents discovered under knowledge.sources; newDocuments is\n' +
|
|
14
|
+
'only the destination for future authored documents. Without --apply scan only reports\n' +
|
|
15
|
+
'candidates.';
|
|
13
16
|
async function runDocsScan(options, output, root) {
|
|
14
17
|
const result = await scanDiscoveredDocuments(root, { apply: options.apply });
|
|
15
18
|
if ('message' in result) {
|
|
@@ -20,20 +23,37 @@ async function runDocsScan(options, output, root) {
|
|
|
20
23
|
output.stdout(`${JSON.stringify(result)}\n`);
|
|
21
24
|
}
|
|
22
25
|
else {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
output.stdout(` ${candidate.kind} ${candidate.path}\n`);
|
|
26
|
+
if (result.candidates.length === 0) {
|
|
27
|
+
output.stdout('No new documents found.\n');
|
|
26
28
|
}
|
|
27
|
-
|
|
29
|
+
else {
|
|
30
|
+
output.stdout(`Scan candidates: ${result.candidates.length}\n`);
|
|
31
|
+
for (const candidate of result.candidates) {
|
|
32
|
+
output.stdout(` ${candidate.kind} ${candidate.path}\n`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
printDiagnostics(output, result.diagnostics);
|
|
36
|
+
for (const action of result.nextActions) {
|
|
37
|
+
output.stdout(`${action}\n`);
|
|
38
|
+
}
|
|
39
|
+
output.stdout(result.ok
|
|
40
|
+
? 'Plan only; rerun with --apply to register them.\n'
|
|
41
|
+
: 'Scan coverage is incomplete; no complete result is claimed.\n');
|
|
28
42
|
}
|
|
29
|
-
return 0;
|
|
43
|
+
return result.ok ? 0 : 1;
|
|
30
44
|
}
|
|
31
45
|
if (options.json) {
|
|
32
46
|
output.stdout(`${JSON.stringify(result)}\n`);
|
|
33
47
|
}
|
|
34
48
|
else {
|
|
35
49
|
output.stdout(`Registered ${result.registered.length} document(s).\n`);
|
|
50
|
+
if (!result.ok) {
|
|
51
|
+
output.stdout('Scan coverage is incomplete; the registration result is not a complete scan.\n');
|
|
52
|
+
}
|
|
36
53
|
printDiagnostics(output, result.diagnostics);
|
|
54
|
+
for (const action of result.nextActions) {
|
|
55
|
+
output.stdout(`${action}\n`);
|
|
56
|
+
}
|
|
37
57
|
}
|
|
38
58
|
return result.ok ? 0 : 1;
|
|
39
59
|
}
|
|
@@ -75,7 +95,7 @@ export async function runDocsCommand(options, output) {
|
|
|
75
95
|
if (options.action === null || options.action === 'help') {
|
|
76
96
|
if (options.json) {
|
|
77
97
|
output.stdout(`${JSON.stringify({
|
|
78
|
-
commands: ['list', 'check', 'archive'],
|
|
98
|
+
commands: ['list', 'check', 'archive', 'scan', 'relocate', 'forget'],
|
|
79
99
|
usage: docsUsage,
|
|
80
100
|
})}\n`);
|
|
81
101
|
}
|
|
@@ -84,22 +104,67 @@ export async function runDocsCommand(options, output) {
|
|
|
84
104
|
}
|
|
85
105
|
return 0;
|
|
86
106
|
}
|
|
107
|
+
if (options.scope !== undefined &&
|
|
108
|
+
options.scope !== null &&
|
|
109
|
+
(options.action !== 'forget' ||
|
|
110
|
+
!['private', 'shared'].includes(options.scope)))
|
|
111
|
+
return invalidArguments(output, options.json, 'Only docs forget accepts --scope private|shared.');
|
|
87
112
|
const resolution = await resolveWorkspaceRoot({ startPath: options.cwd });
|
|
88
113
|
const serviceRoot = resolution.root ?? options.cwd;
|
|
89
|
-
if (!['list', 'check', 'archive', 'scan'].includes(options.action)) {
|
|
114
|
+
if (!['list', 'check', 'archive', 'scan', 'relocate', 'forget'].includes(options.action)) {
|
|
90
115
|
return invalidArguments(output, options.json, `unknown docs action: ${options.action}`);
|
|
91
116
|
}
|
|
92
|
-
if (
|
|
93
|
-
|
|
117
|
+
if (['archive', 'relocate', 'forget'].includes(options.action) &&
|
|
118
|
+
options.argument === null) {
|
|
119
|
+
return invalidArguments(output, options.json, `docs ${options.action} requires a documentId`);
|
|
94
120
|
}
|
|
95
|
-
if (
|
|
121
|
+
if (!['archive', 'relocate', 'forget'].includes(options.action) &&
|
|
122
|
+
options.argument !== null) {
|
|
96
123
|
return invalidArguments(output, options.json, `docs ${options.action} does not accept an argument`);
|
|
97
124
|
}
|
|
98
125
|
if (options.action === 'scan') {
|
|
99
126
|
return runDocsScan(options, output, serviceRoot);
|
|
100
127
|
}
|
|
128
|
+
if ((options.action === 'relocate' || options.action === 'forget') &&
|
|
129
|
+
options.argument !== null) {
|
|
130
|
+
const location = options.action === 'relocate'
|
|
131
|
+
? documentLocationSchema.safeParse({
|
|
132
|
+
kind: 'workspace',
|
|
133
|
+
path: options.targetPath,
|
|
134
|
+
})
|
|
135
|
+
: null;
|
|
136
|
+
if (location && !location.success)
|
|
137
|
+
return invalidArguments(output, options.json, 'docs relocate requires a normalized workspace-relative target path.');
|
|
138
|
+
if (!options.apply) {
|
|
139
|
+
const plan = {
|
|
140
|
+
schema: 'pappra/docs-metadata-plan/1',
|
|
141
|
+
ok: true,
|
|
142
|
+
action: options.action,
|
|
143
|
+
documentId: options.argument,
|
|
144
|
+
scope: options.scope ?? null,
|
|
145
|
+
location: location?.success ? location.data : null,
|
|
146
|
+
applied: false,
|
|
147
|
+
};
|
|
148
|
+
output.stdout(options.json
|
|
149
|
+
? `${JSON.stringify(plan)}\n`
|
|
150
|
+
: `Plan only: ${options.action} ${options.argument}; document content is preserved. Rerun with --apply.\n`);
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
const service = new KnowledgeService(serviceRoot);
|
|
154
|
+
const result = location?.success
|
|
155
|
+
? await service.relocate(options.argument, location.data)
|
|
156
|
+
: await service.forget(options.argument, options.scope === 'private' || options.scope === 'shared'
|
|
157
|
+
? options.scope
|
|
158
|
+
: undefined);
|
|
159
|
+
output.stdout(options.json
|
|
160
|
+
? `${JSON.stringify({ schema: 'pappra/docs-metadata-result/1', action: options.action, ...result })}\n`
|
|
161
|
+
: `${options.action}: ${result.ok ? 'applied' : result.status}\n`);
|
|
162
|
+
if (!options.json)
|
|
163
|
+
printDiagnostics(output, result.diagnostics);
|
|
164
|
+
return result.ok ? 0 : 1;
|
|
165
|
+
}
|
|
101
166
|
if (options.apply) {
|
|
102
|
-
return invalidArguments(output, options.json, 'only docs scan
|
|
167
|
+
return invalidArguments(output, options.json, 'only docs scan, relocate and forget accept --apply');
|
|
103
168
|
}
|
|
104
169
|
if (options.action === 'archive' && options.argument !== null) {
|
|
105
170
|
const service = new KnowledgeService(serviceRoot);
|
|
@@ -142,6 +207,15 @@ export async function runDocsCommand(options, output) {
|
|
|
142
207
|
else {
|
|
143
208
|
for (const record of result.records)
|
|
144
209
|
printDocument(output, record);
|
|
210
|
+
if (result.records.length === 0 && !options.includePrivate && result.ok) {
|
|
211
|
+
const command = options.includeArchived
|
|
212
|
+
? 'pappra docs list --include-private --include-archived'
|
|
213
|
+
: 'pappra docs list --include-private';
|
|
214
|
+
output.stdout(`No documents in the default view. Private documents are hidden; run: ${command}\n`);
|
|
215
|
+
if (!options.includeArchived) {
|
|
216
|
+
output.stdout('Archived documents also remain hidden; add --include-archived to include them.\n');
|
|
217
|
+
}
|
|
218
|
+
}
|
|
145
219
|
printDiagnostics(output, result.diagnostics);
|
|
146
220
|
}
|
|
147
221
|
return result.ok ? 0 : 1;
|
|
@@ -4,7 +4,7 @@ export declare const hostUsage: string;
|
|
|
4
4
|
export interface HostCommandOptions {
|
|
5
5
|
readonly cwd: string;
|
|
6
6
|
readonly json: boolean;
|
|
7
|
-
readonly action: 'detect' | 'describe' | 'plan' | 'install' | 'verify' | 'bundle' | 'mcp' | 'probe' | null;
|
|
7
|
+
readonly action: 'detect' | 'describe' | 'plan' | 'install' | 'uninstall' | 'verify' | 'bundle' | 'mcp' | 'probe' | null;
|
|
8
8
|
readonly host: HostName | null;
|
|
9
9
|
readonly hostRoot: string | null;
|
|
10
10
|
readonly hostVersion: string | null;
|
|
@@ -13,6 +13,12 @@ export interface HostCommandOptions {
|
|
|
13
13
|
readonly subAction: string | null;
|
|
14
14
|
readonly out: string | null;
|
|
15
15
|
readonly mode: 'project-settings' | 'plugin' | null;
|
|
16
|
+
/** Explicit private bootstrap binding; Pi bundle exports only. */
|
|
17
|
+
readonly bootstrapConfig: string | null;
|
|
18
|
+
/** Explicit validated task/session binding; recovery exports are Pi-only. */
|
|
19
|
+
readonly recoveryConfig: string | null;
|
|
20
|
+
/** Opt-in Pi session-transition command extension; it is not native takeover. */
|
|
21
|
+
readonly transitionExtension: boolean;
|
|
16
22
|
readonly marketplace: boolean;
|
|
17
23
|
readonly scope: 'project' | 'user' | null;
|
|
18
24
|
}
|
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
import { homedir } from 'node:os';
|
|
2
|
-
import { join, resolve } from 'node:path';
|
|
2
|
+
import { isAbsolute, join, resolve } from 'node:path';
|
|
3
3
|
import { HostIntegrationService } from '../../hosts/integration/service.js';
|
|
4
|
-
import { exportHostPluginBundle } from '../../hosts/integration/bundle-export.js';
|
|
4
|
+
import { exportHostPluginBundle, } from '../../hosts/integration/bundle-export.js';
|
|
5
|
+
import { readPiBootstrapConfig } from '../../hosts/integration/bootstrap-config.js';
|
|
6
|
+
import { readPiRecoveryConfig } from '../../hosts/integration/recovery-config.js';
|
|
5
7
|
import { applyHostMcp, planHostMcp, verifyHostMcp, } from '../../app/host-mcp.js';
|
|
6
8
|
import { probeHost } from '../../app/host-probe.js';
|
|
7
9
|
import { HOST_SUPPORT, isSupportedVersion, } from '../../hosts/integration/support.js';
|
|
8
|
-
import { getPackageInfo } from '../../package-info.js';
|
|
9
|
-
export const hostUsage = 'pappra host <detect|describe|plan|install|verify|bundle|mcp> --host <pi|codex|claude>\n' +
|
|
10
|
+
import { getPackageInfo, getPackageRoot } from '../../package-info.js';
|
|
11
|
+
export const hostUsage = 'pappra host <detect|describe|probe|plan|install|uninstall|verify|bundle|mcp> --host <pi|codex|claude>\n' +
|
|
10
12
|
' [--host-root <dir>] [--host-version <version>] [--out <dir>]\n' +
|
|
11
|
-
' [--mode project-settings|plugin] [--apply] [--json]\n' +
|
|
13
|
+
' [--mode project-settings|plugin] [--scope project|user] [--marketplace] [--apply] [--json]\n' +
|
|
14
|
+
' probe --host <name> [--host-root <dir>] [--json]\n' +
|
|
15
|
+
' uninstall --host <name> [--host-root <dir> | --scope user] [--apply] [--force]\n' +
|
|
16
|
+
' --force asserts all host writers are stopped and archives unknown locks; edited assets remain preserved.\n' +
|
|
17
|
+
' mcp <plan|install|verify> --host <name> [--host-root <dir>] [--apply] [--json]\n' +
|
|
18
|
+
' bundle --host pi --out <new-private-dir> [--bootstrap-config <abs-file> |\n' +
|
|
19
|
+
' --recovery-config <abs-file>] [--transition-extension]\n' +
|
|
12
20
|
'\n' +
|
|
13
21
|
'bundle exports a host-native plugin/package directory and never registers it or\n' +
|
|
14
|
-
'claims host callability.'
|
|
22
|
+
'claims host callability. Recovery and transition extensions are opt-in Pi bundle\n' +
|
|
23
|
+
'artifacts; --recovery-config must pin an exact task-local session and binding.\n' +
|
|
24
|
+
'Exports do not install, trust, load, launch or transfer; native quiescence and\n' +
|
|
25
|
+
'interactive session takeover remain unsupported.';
|
|
15
26
|
/** Codex only loads lifecycle hooks from its user configuration directory. */
|
|
16
27
|
function codexHome() {
|
|
17
28
|
const configured = process.env['CODEX_HOME'];
|
|
@@ -66,8 +77,9 @@ export async function runHostCommand(options, output) {
|
|
|
66
77
|
}
|
|
67
78
|
if (options.action !== 'plan' &&
|
|
68
79
|
options.action !== 'install' &&
|
|
80
|
+
options.action !== 'uninstall' &&
|
|
69
81
|
options.action !== 'verify') {
|
|
70
|
-
output.stderr('pappra host: --scope user is only valid for plan, install, or verify.\n');
|
|
82
|
+
output.stderr('pappra host: --scope user is only valid for plan, install, uninstall, or verify.\n');
|
|
71
83
|
return 2;
|
|
72
84
|
}
|
|
73
85
|
}
|
|
@@ -197,15 +209,109 @@ export async function runHostCommand(options, output) {
|
|
|
197
209
|
}
|
|
198
210
|
return diagnosticStatus(result.status);
|
|
199
211
|
}
|
|
212
|
+
if (options.action === 'uninstall') {
|
|
213
|
+
const result = await service.uninstall(options.host, {
|
|
214
|
+
...target,
|
|
215
|
+
apply: options.apply,
|
|
216
|
+
force: options.force,
|
|
217
|
+
});
|
|
218
|
+
if (options.json)
|
|
219
|
+
output.stdout(`${JSON.stringify(result)}\n`);
|
|
220
|
+
else {
|
|
221
|
+
output.stdout(`Status: ${result.status}\n`);
|
|
222
|
+
for (const file of result.removedFiles)
|
|
223
|
+
output.stdout(` removed ${file}\n`);
|
|
224
|
+
for (const file of result.retainedPaths)
|
|
225
|
+
output.stdout(` preserved ${file}\n`);
|
|
226
|
+
for (const file of result.quarantinedLocks)
|
|
227
|
+
output.stdout(` archived lock ${file}\n`);
|
|
228
|
+
if (!options.apply)
|
|
229
|
+
output.stdout(' plan only; rerun with --apply to remove managed wiring.\n');
|
|
230
|
+
printDiagnostics(output, result.diagnostics);
|
|
231
|
+
}
|
|
232
|
+
return result.ok ? 0 : 1;
|
|
233
|
+
}
|
|
200
234
|
if (options.action === 'bundle') {
|
|
201
235
|
if (options.out === null) {
|
|
202
236
|
output.stderr('pappra host bundle requires --out <dir>.\n');
|
|
203
237
|
return 2;
|
|
204
238
|
}
|
|
239
|
+
if (options.bootstrapConfig !== null) {
|
|
240
|
+
if (options.host !== 'pi') {
|
|
241
|
+
output.stderr('pappra host bundle: --bootstrap-config requires --host pi.\n');
|
|
242
|
+
return 2;
|
|
243
|
+
}
|
|
244
|
+
if (!isAbsolute(options.bootstrapConfig)) {
|
|
245
|
+
output.stderr('pappra host bundle: --bootstrap-config must be an absolute path.\n');
|
|
246
|
+
return 2;
|
|
247
|
+
}
|
|
248
|
+
if (options.marketplace || options.mode !== null || options.apply) {
|
|
249
|
+
output.stderr('pappra host bundle: --bootstrap-config cannot be combined with --marketplace, --mode or --apply.\n');
|
|
250
|
+
return 2;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
205
253
|
if (!isSupportedVersion(options.host, options.hostVersion)) {
|
|
206
254
|
output.stderr(`Host ${options.host} version ${options.hostVersion ?? '(unknown)'} is outside the pinned ${HOST_SUPPORT[options.host].version} support matrix.\n`);
|
|
207
255
|
return 1;
|
|
208
256
|
}
|
|
257
|
+
let bootstrap;
|
|
258
|
+
if (options.bootstrapConfig !== null) {
|
|
259
|
+
const loaded = readPiBootstrapConfig(options.bootstrapConfig);
|
|
260
|
+
if (loaded.ok === false) {
|
|
261
|
+
if (options.json) {
|
|
262
|
+
output.stdout(`${JSON.stringify({
|
|
263
|
+
ok: false,
|
|
264
|
+
command: 'host',
|
|
265
|
+
action: 'bundle',
|
|
266
|
+
code: loaded.code,
|
|
267
|
+
message: loaded.message,
|
|
268
|
+
})}\n`);
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
output.stderr(`pappra host bundle: ${loaded.message}\n`);
|
|
272
|
+
}
|
|
273
|
+
return 1;
|
|
274
|
+
}
|
|
275
|
+
bootstrap = {
|
|
276
|
+
config: loaded.config,
|
|
277
|
+
configBytes: loaded.bytes,
|
|
278
|
+
configDigest: loaded.digest,
|
|
279
|
+
artifactPath: join(getPackageRoot(), 'dist/hosts/integration/pappra-bootstrap-extension.mjs'),
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
let recovery;
|
|
283
|
+
if (options.recoveryConfig !== null) {
|
|
284
|
+
if (options.host !== 'pi') {
|
|
285
|
+
output.stderr('pappra host bundle: --recovery-config requires --host pi.\n');
|
|
286
|
+
return 2;
|
|
287
|
+
}
|
|
288
|
+
if (!isAbsolute(options.recoveryConfig) ||
|
|
289
|
+
options.bootstrapConfig !== null ||
|
|
290
|
+
options.marketplace ||
|
|
291
|
+
options.mode !== null ||
|
|
292
|
+
options.apply) {
|
|
293
|
+
output.stderr('pappra host bundle: --recovery-config requires an absolute path and cannot be combined with --bootstrap-config, --marketplace, --mode or --apply.\n');
|
|
294
|
+
return 2;
|
|
295
|
+
}
|
|
296
|
+
const loaded = readPiRecoveryConfig(options.recoveryConfig);
|
|
297
|
+
if (loaded.ok === false) {
|
|
298
|
+
output.stderr(`pappra host bundle: recovery config validation failed (${loaded.code}).\n`);
|
|
299
|
+
return 1;
|
|
300
|
+
}
|
|
301
|
+
recovery = {
|
|
302
|
+
configFile: options.recoveryConfig,
|
|
303
|
+
artifactPath: join(getPackageRoot(), 'dist/hosts/integration/pappra-recovery-extension.mjs'),
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
if (options.transitionExtension &&
|
|
307
|
+
(options.host !== 'pi' ||
|
|
308
|
+
options.bootstrapConfig !== null ||
|
|
309
|
+
options.marketplace ||
|
|
310
|
+
options.mode !== null ||
|
|
311
|
+
options.apply)) {
|
|
312
|
+
output.stderr('pappra host bundle: --transition-extension requires a plain Pi bundle and cannot be combined with --bootstrap-config, --marketplace, --mode or --apply.\n');
|
|
313
|
+
return 2;
|
|
314
|
+
}
|
|
209
315
|
try {
|
|
210
316
|
const exported = await exportHostPluginBundle({
|
|
211
317
|
host: options.host,
|
|
@@ -213,6 +319,15 @@ export async function runHostCommand(options, output) {
|
|
|
213
319
|
outDir: options.out,
|
|
214
320
|
packageVersion: getPackageInfo().version,
|
|
215
321
|
marketplace: options.marketplace,
|
|
322
|
+
...(bootstrap === undefined ? {} : { bootstrap }),
|
|
323
|
+
...(recovery === undefined ? {} : { recovery }),
|
|
324
|
+
...(options.transitionExtension
|
|
325
|
+
? {
|
|
326
|
+
transition: {
|
|
327
|
+
artifactPath: join(getPackageRoot(), 'dist/hosts/integration/pappra-session-transition-extension.mjs'),
|
|
328
|
+
},
|
|
329
|
+
}
|
|
330
|
+
: {}),
|
|
216
331
|
});
|
|
217
332
|
if (options.json) {
|
|
218
333
|
output.stdout(`${JSON.stringify({ ok: true, command: 'host', action: 'bundle', ...exported })}\n`);
|