@phyzess/pappra 0.1.0-beta.14 → 0.1.0-beta.19
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 +133 -14
- package/assets/integrations/skills/pappra/SKILL.md +56 -7
- package/assets/integrations/skills/pappra/references/collaboration.md +646 -0
- package/assets/integrations/skills/pappra/references/environment.md +367 -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-request.d.ts +50 -0
- package/dist/app/collab-session-transition-request.js +339 -0
- package/dist/app/collab-session-transition-validation.d.ts +19 -0
- package/dist/app/collab-session-transition-validation.js +44 -0
- package/dist/app/collab-session-transition.d.ts +181 -0
- package/dist/app/collab-session-transition.js +2970 -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 +104 -3
- 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/collaboration-router.d.ts +17 -0
- package/dist/cli/collaboration-router.js +604 -0
- 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/options.d.ts +806 -0
- package/dist/cli/options.js +293 -0
- package/dist/cli/run.js +280 -310
- 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 +90 -67
- 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 +37 -35
- package/skills/pappra/SKILL.md +56 -7
- package/skills/pappra/references/collaboration.md +646 -0
- package/skills/pappra/references/environment.md +367 -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,75 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { applySessionTransition, loadSessionTransitionRequest, planSessionTransition, } from '../../app/collab-session-transition.js';
|
|
3
|
+
export const collaborationTransitionUsage = 'pappra collab transition <plan|apply> --task-root <abs> --request <abs request.json> [--json]\n\n' +
|
|
4
|
+
'Plan is read-only. Apply resumes one guarded durable transition stage at a time.\n' +
|
|
5
|
+
'Pi idle/settled events, a managed freeze latch and transcript data are not native\n' +
|
|
6
|
+
'quiescence proof. Unsupported host proof blocks before successor launch or claim\n' +
|
|
7
|
+
'transfer. ACK and first-work messages must be registered and applied; task retirement\n' +
|
|
8
|
+
'writes a reversible marker only and never archives the native Pi session.';
|
|
9
|
+
function emitHuman(report, output) {
|
|
10
|
+
output.stdout(`Session transition ${report.action}: ${report.status}${report.code === null ? '' : ` (${report.code})`}.\n`);
|
|
11
|
+
if (report.message !== null)
|
|
12
|
+
output.stdout(` ${report.message}\n`);
|
|
13
|
+
output.stdout(` task: ${report.task_id ?? '<unavailable>'} (${report.task_root})\n`);
|
|
14
|
+
output.stdout(` transition: ${report.transition_id || '<unavailable>'}; stage: ${report.stage}\n`);
|
|
15
|
+
if (report.next_action !== null)
|
|
16
|
+
output.stdout(` next: ${report.next_action}\n`);
|
|
17
|
+
if (report.steps.length > 0) {
|
|
18
|
+
output.stdout(' stages:\n');
|
|
19
|
+
for (const item of report.steps)
|
|
20
|
+
output.stdout(` ${item.step}: ${item.status}${item.code === null ? '' : ` (${item.code})`}${item.detail === null ? '' : ` — ${item.detail}`}\n`);
|
|
21
|
+
}
|
|
22
|
+
if (report.route_transfer !== null)
|
|
23
|
+
output.stdout(` route/claims: ${JSON.stringify(report.route_transfer)}\n`);
|
|
24
|
+
if (report.first_work !== null)
|
|
25
|
+
output.stdout(` first work: ${JSON.stringify(report.first_work)}\n`);
|
|
26
|
+
if (report.archive !== null)
|
|
27
|
+
output.stdout(` retirement: ${JSON.stringify(report.archive)}\n`);
|
|
28
|
+
output.stdout(` capabilities: quiescence ${report.capabilities.supported_quiescence}, native archive ${report.capabilities.native_session_archive}, route exclusion ${report.capabilities.notification_route_exclusion}\n`);
|
|
29
|
+
if (report.limits.length > 0)
|
|
30
|
+
output.stdout(` limits: ${report.limits.join('; ')}\n`);
|
|
31
|
+
}
|
|
32
|
+
function invalid(options, output, code, message) {
|
|
33
|
+
if (options.json)
|
|
34
|
+
output.stdout(`${JSON.stringify({ ok: false, status: 'invalid', code, message })}\n`);
|
|
35
|
+
else {
|
|
36
|
+
output.stderr(`pappra: ${message}\n`);
|
|
37
|
+
output.stderr(`${collaborationTransitionUsage}\n`);
|
|
38
|
+
}
|
|
39
|
+
return 2;
|
|
40
|
+
}
|
|
41
|
+
export async function runCollaborationTransitionCommand(options, output, dependencies = {}) {
|
|
42
|
+
if (options.action === null)
|
|
43
|
+
return invalid(options, output, 'transition_action_required', 'collab transition requires plan or apply.');
|
|
44
|
+
if (options.taskRoot === null || options.requestFile === null)
|
|
45
|
+
return invalid(options, output, 'required_option_missing', 'collab transition requires --task-root and --request.');
|
|
46
|
+
if (!path.isAbsolute(options.taskRoot) ||
|
|
47
|
+
!path.isAbsolute(options.requestFile))
|
|
48
|
+
return invalid(options, output, 'absolute_path_required', '--task-root and --request must be absolute paths.');
|
|
49
|
+
const loaded = loadSessionTransitionRequest(options.requestFile);
|
|
50
|
+
if (!loaded.ok) {
|
|
51
|
+
if (options.json)
|
|
52
|
+
output.stdout(`${JSON.stringify({ ok: false, status: loaded.kind, code: loaded.code, message: loaded.message, next_action: loaded.next_action })}\n`);
|
|
53
|
+
else {
|
|
54
|
+
output.stderr(`${loaded.code}: ${loaded.message}\n`);
|
|
55
|
+
if (loaded.next_action !== null)
|
|
56
|
+
output.stderr(`${loaded.next_action}\n`);
|
|
57
|
+
}
|
|
58
|
+
return 2;
|
|
59
|
+
}
|
|
60
|
+
if (path.resolve(loaded.value.request.task_root) !==
|
|
61
|
+
path.resolve(options.taskRoot))
|
|
62
|
+
return invalid(options, output, 'task_root_mismatch', 'The request task_root does not equal --task-root.');
|
|
63
|
+
const report = options.action === 'plan'
|
|
64
|
+
? await planSessionTransition(loaded.value, dependencies)
|
|
65
|
+
: await applySessionTransition(loaded.value, dependencies);
|
|
66
|
+
if (options.json)
|
|
67
|
+
output.stdout(`${JSON.stringify(report)}\n`);
|
|
68
|
+
else
|
|
69
|
+
emitHuman(report, output);
|
|
70
|
+
if (report.status === 'invalid')
|
|
71
|
+
return 2;
|
|
72
|
+
if (report.action === 'apply' && report.status === 'waiting')
|
|
73
|
+
return 1;
|
|
74
|
+
return report.ok ? 0 : 1;
|
|
75
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type WorkExecutionAdapter } from '../../app/collab-work-execution.js';
|
|
2
|
+
import type { CliOutput } from '../output.js';
|
|
3
|
+
export declare const collaborationWorkRunUsage: string;
|
|
4
|
+
export interface CollaborationWorkRunOptions {
|
|
5
|
+
readonly requestFile: string | null;
|
|
6
|
+
readonly apply: boolean;
|
|
7
|
+
readonly json: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface CollaborationWorkRunParse {
|
|
10
|
+
readonly options: CollaborationWorkRunOptions;
|
|
11
|
+
readonly errors: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
export interface WorkExecutionRequestFile {
|
|
14
|
+
readonly schema: 'pappra/collab-work-execution-request/1';
|
|
15
|
+
readonly task_root: string;
|
|
16
|
+
readonly plan_file: string;
|
|
17
|
+
readonly binding_file: string;
|
|
18
|
+
readonly caller: {
|
|
19
|
+
readonly agent_id: string;
|
|
20
|
+
readonly session_id: string;
|
|
21
|
+
readonly harness: string;
|
|
22
|
+
readonly cwd: string;
|
|
23
|
+
};
|
|
24
|
+
readonly caller_pane: string;
|
|
25
|
+
readonly capability_cards: readonly {
|
|
26
|
+
readonly assignment_id: string;
|
|
27
|
+
readonly capabilities_file: string;
|
|
28
|
+
}[];
|
|
29
|
+
readonly max_concurrency?: number;
|
|
30
|
+
}
|
|
31
|
+
export declare function parseCollaborationWorkRunArgs(argv: readonly string[]): CollaborationWorkRunParse;
|
|
32
|
+
export declare function runCollaborationWorkRunCommand(options: CollaborationWorkRunOptions, output: CliOutput, deps?: {
|
|
33
|
+
readonly adapter?: WorkExecutionAdapter;
|
|
34
|
+
}): Promise<number>;
|
|
@@ -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
|
}
|