@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,69 @@
|
|
|
1
|
+
import { readBoundedFile } from '../../app/bounded-file.js';
|
|
2
|
+
import { expandRolePlan, aggregateRolePlan, } from '../../app/collab-role-plan.js';
|
|
3
|
+
import { inspectWorkPlan } from '../../app/collab-work-plan.js';
|
|
4
|
+
import { canonicalJson } from '../../collab/envelope.js';
|
|
5
|
+
export const collaborationRolePlanUsage = 'pappra collab role-plan expand --request <abs role-plan.json> [--json]\n' +
|
|
6
|
+
'pappra collab role-plan aggregate --request <abs role-plan.json> --task-root <abs> --config <abs expanded-plan.json> [--json]\n\n' +
|
|
7
|
+
'Read-only writer/reviewer expansion and authoritative task-result aggregation.\n' +
|
|
8
|
+
'Save the returned plan, then use collab plan/work-run for existing admission and dispatch.\n' +
|
|
9
|
+
'Roles never grant authority; delivery never implies acceptance.';
|
|
10
|
+
function loadJson(file) {
|
|
11
|
+
if (file === null)
|
|
12
|
+
throw new Error('An absolute input file is required.');
|
|
13
|
+
const loaded = readBoundedFile(file, 512 * 1024);
|
|
14
|
+
if (!loaded.ok)
|
|
15
|
+
throw new Error(`Input refused: ${loaded.code}.`);
|
|
16
|
+
try {
|
|
17
|
+
return JSON.parse(loaded.text);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
throw new Error('Input must be JSON.');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export async function runCollaborationRolePlanCommand(options, output) {
|
|
24
|
+
const emit = (value) => {
|
|
25
|
+
output.stdout(`${JSON.stringify(value, null, options.json ? undefined : 2)}\n`);
|
|
26
|
+
};
|
|
27
|
+
try {
|
|
28
|
+
if (options.action !== 'expand' && options.action !== 'aggregate')
|
|
29
|
+
throw new Error('role-plan accepts expand or aggregate.');
|
|
30
|
+
if (options.action === 'expand' &&
|
|
31
|
+
(options.taskRoot !== null || options.planFile !== null))
|
|
32
|
+
throw new Error('expand accepts only --request and --json.');
|
|
33
|
+
const expanded = expandRolePlan(loadJson(options.requestFile));
|
|
34
|
+
if (!expanded.ok) {
|
|
35
|
+
emit(expanded);
|
|
36
|
+
return 2;
|
|
37
|
+
}
|
|
38
|
+
if (options.action === 'expand') {
|
|
39
|
+
emit(expanded);
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
if (options.taskRoot === null || options.planFile === null)
|
|
43
|
+
throw new Error('aggregate requires --task-root and --config.');
|
|
44
|
+
if (canonicalJson(loadJson(options.planFile)) !== canonicalJson(expanded.plan))
|
|
45
|
+
throw new Error('Persisted plan differs from the expanded role request.');
|
|
46
|
+
const report = await inspectWorkPlan({
|
|
47
|
+
taskRoot: options.taskRoot,
|
|
48
|
+
planFile: options.planFile,
|
|
49
|
+
});
|
|
50
|
+
const result = aggregateRolePlan(expanded, report.core ?? {
|
|
51
|
+
ok: false,
|
|
52
|
+
diagnostics: report.diagnostics.map((entry) => ({
|
|
53
|
+
...entry,
|
|
54
|
+
node_id: null,
|
|
55
|
+
})),
|
|
56
|
+
});
|
|
57
|
+
emit(result);
|
|
58
|
+
return result.outcome === 'unknown' || result.outcome === 'missing' ? 1 : 0;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
emit({
|
|
62
|
+
ok: false,
|
|
63
|
+
status: 'invalid',
|
|
64
|
+
code: 'invalid_role_plan_request',
|
|
65
|
+
message: error instanceof Error ? error.message : 'Role plan request failed.',
|
|
66
|
+
});
|
|
67
|
+
return 2;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { watchRoleOrchestration } from '../../app/collab-role-events.js';
|
|
2
|
+
import type { CliOutput } from '../output.js';
|
|
3
|
+
export declare const collaborationRoleRunUsage: string;
|
|
4
|
+
export declare function runCollaborationRoleRunCommand(options: {
|
|
5
|
+
readonly requestFile: string | null;
|
|
6
|
+
readonly apply: boolean;
|
|
7
|
+
readonly watch?: boolean;
|
|
8
|
+
readonly json: boolean;
|
|
9
|
+
}, output: CliOutput, deps?: {
|
|
10
|
+
readonly watch?: typeof watchRoleOrchestration;
|
|
11
|
+
}): Promise<number>;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { loadRoleRunRequest, watchRoleOrchestration, } from '../../app/collab-role-events.js';
|
|
2
|
+
import { tickRoleOrchestration } from '../../app/collab-role-orchestration.js';
|
|
3
|
+
import { expandRolePlan } from '../../app/collab-role-plan.js';
|
|
4
|
+
import { inspectWorkPlan } from '../../app/collab-work-plan.js';
|
|
5
|
+
import { readBoundedFile } from '../../app/bounded-file.js';
|
|
6
|
+
import { canonicalJson } from '../../collab/envelope.js';
|
|
7
|
+
import { managedPiRepairDependencies } from '../../app/managed-pi-repair-stop.js';
|
|
8
|
+
export const collaborationRoleRunUsage = 'pappra collab role-run --request <abs role-orchestration.json> [--apply] [--watch] [--json]\n\n' +
|
|
9
|
+
'Plan reads authoritative role/dependency state without effects. Apply handles one\n' +
|
|
10
|
+
'bounded event tick, reserves before dispatch and never infers acceptance.\n' +
|
|
11
|
+
'--watch requires --apply and re-evaluates on relevant task/request/capability events.\n' +
|
|
12
|
+
'Repeated or ambiguous effects are reconciled; rejected work requires an authorized repair attempt.';
|
|
13
|
+
const PUBLIC_ERRORS = new Set([
|
|
14
|
+
'role_request_required',
|
|
15
|
+
'role_request_invalid',
|
|
16
|
+
'role_request_invalid_json',
|
|
17
|
+
'role_request_path_not_absolute',
|
|
18
|
+
'role_request_symlink',
|
|
19
|
+
'role_request_not_regular',
|
|
20
|
+
'role_request_too_large',
|
|
21
|
+
'role_request_unreadable',
|
|
22
|
+
'role_plan_file_mismatch',
|
|
23
|
+
'watch_requires_apply',
|
|
24
|
+
'role_event_request_path_not_absolute',
|
|
25
|
+
'role_event_task_unavailable',
|
|
26
|
+
'role_event_task_root_mismatch',
|
|
27
|
+
'role_event_watch_initialization_failed',
|
|
28
|
+
]);
|
|
29
|
+
function safeErrorCode(error) {
|
|
30
|
+
if (!(error instanceof Error))
|
|
31
|
+
return 'role_run_failed';
|
|
32
|
+
return PUBLIC_ERRORS.has(error.message) ? error.message : 'role_run_failed';
|
|
33
|
+
}
|
|
34
|
+
export async function runCollaborationRoleRunCommand(options, output, deps = {}) {
|
|
35
|
+
const emit = (value) => output.stdout(`${JSON.stringify(value, null, options.json ? undefined : 2)}\n`);
|
|
36
|
+
try {
|
|
37
|
+
if (options.watch && !options.apply)
|
|
38
|
+
throw new Error('watch_requires_apply');
|
|
39
|
+
if (!options.requestFile)
|
|
40
|
+
throw new Error('role_request_required');
|
|
41
|
+
if (options.watch) {
|
|
42
|
+
return await runWatch(options.requestFile, emit, deps.watch ?? watchRoleOrchestration);
|
|
43
|
+
}
|
|
44
|
+
const request = loadRoleRunRequest(options.requestFile);
|
|
45
|
+
if (!options.apply) {
|
|
46
|
+
const expanded = expandRolePlan(request.role_plan);
|
|
47
|
+
if (!expanded.ok) {
|
|
48
|
+
emit(expanded);
|
|
49
|
+
return 2;
|
|
50
|
+
}
|
|
51
|
+
const plan = readBoundedFile(request.execution.plan_file, 512 * 1024);
|
|
52
|
+
if (!plan.ok ||
|
|
53
|
+
canonicalJson(JSON.parse(plan.text)) !== canonicalJson(expanded.plan))
|
|
54
|
+
throw new Error('role_plan_file_mismatch');
|
|
55
|
+
const report = await inspectWorkPlan({
|
|
56
|
+
taskRoot: request.execution.task_root,
|
|
57
|
+
planFile: request.execution.plan_file,
|
|
58
|
+
});
|
|
59
|
+
emit({
|
|
60
|
+
schema: 'pappra/collab-role-orchestration-plan/1',
|
|
61
|
+
status: report.ok ? 'planned' : 'blocked',
|
|
62
|
+
effect: 'none',
|
|
63
|
+
inspection: report,
|
|
64
|
+
});
|
|
65
|
+
return report.ok ? 0 : 1;
|
|
66
|
+
}
|
|
67
|
+
const repair = managedPiRepairDependencies(request);
|
|
68
|
+
const report = await tickRoleOrchestration(request, repair ? { repair } : {});
|
|
69
|
+
emit(report);
|
|
70
|
+
return [
|
|
71
|
+
'blocked',
|
|
72
|
+
'reconciliation-required',
|
|
73
|
+
'repair-required',
|
|
74
|
+
'repair-exhausted',
|
|
75
|
+
'budget-exhausted',
|
|
76
|
+
].includes(report.status)
|
|
77
|
+
? 1
|
|
78
|
+
: 0;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
emit({ ok: false, status: 'invalid', code: safeErrorCode(error) });
|
|
82
|
+
return 2;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function runWatch(requestFile, emit, watch) {
|
|
86
|
+
emit({
|
|
87
|
+
schema: 'pappra/collab-role-orchestration-watch/1',
|
|
88
|
+
status: 'watching',
|
|
89
|
+
});
|
|
90
|
+
let resolveStop = null;
|
|
91
|
+
let stopped = false;
|
|
92
|
+
const stop = new Promise((resolve) => {
|
|
93
|
+
resolveStop = resolve;
|
|
94
|
+
});
|
|
95
|
+
const onSignal = (code) => () => {
|
|
96
|
+
if (stopped)
|
|
97
|
+
return;
|
|
98
|
+
stopped = true;
|
|
99
|
+
resolveStop?.(code);
|
|
100
|
+
};
|
|
101
|
+
const onInterrupt = onSignal(130);
|
|
102
|
+
const onTerminate = onSignal(143);
|
|
103
|
+
process.once('SIGINT', onInterrupt);
|
|
104
|
+
process.once('SIGTERM', onTerminate);
|
|
105
|
+
let watcher = null;
|
|
106
|
+
try {
|
|
107
|
+
watcher = await watch(requestFile, (result) => emit(result));
|
|
108
|
+
const signalCode = await stop;
|
|
109
|
+
const status = watcher.status();
|
|
110
|
+
emit({
|
|
111
|
+
schema: 'pappra/collab-role-orchestration-watch/1',
|
|
112
|
+
status: 'stopped',
|
|
113
|
+
result: status.result,
|
|
114
|
+
error: status.error,
|
|
115
|
+
});
|
|
116
|
+
return signalCode;
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
try {
|
|
120
|
+
if (watcher)
|
|
121
|
+
await watcher.close();
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
process.removeListener('SIGINT', onInterrupt);
|
|
125
|
+
process.removeListener('SIGTERM', onTerminate);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type RolloverAction } from '../../app/collab-rollover.js';
|
|
2
|
+
import type { CliOutput } from '../output.js';
|
|
3
|
+
export declare const collaborationRolloverUsage: string;
|
|
4
|
+
export interface CollaborationRolloverOptions {
|
|
5
|
+
readonly action: RolloverAction;
|
|
6
|
+
readonly taskRoot: string | null;
|
|
7
|
+
readonly requestFile: string | null;
|
|
8
|
+
readonly json: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function runCollaborationRolloverCommand(options: CollaborationRolloverOptions, output: CliOutput): Promise<number>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { COLLAB_ROLLOVER_REPORT_SCHEMA, inspectOrPlanRollover, loadRolloverRequest, } from '../../app/collab-rollover.js';
|
|
3
|
+
export const collaborationRolloverUsage = 'pappra collab rollover <inspect|plan> --task-root <abs> --request <abs request.json> [--json]\n\n' +
|
|
4
|
+
'Read-only rollover inspection and planning against the authoritative task record\n' +
|
|
5
|
+
'and one exact linked continuity handoff bundle. Nothing is claimed, transferred,\n' +
|
|
6
|
+
'launched, archived, routed, notified or written, and no native query is made.\n\n' +
|
|
7
|
+
'The request document is bounded (64 KiB) and separately versioned\n' +
|
|
8
|
+
'(schema pappra/collaboration-rollover-request/1). It names the absolute task root,\n' +
|
|
9
|
+
'the exact bundle reference and digest, and either a recorded intent id or a\n' +
|
|
10
|
+
'proposed intent. --task-root must equal the request task_root.\n\n' +
|
|
11
|
+
'There is no apply action. A caller-supplied stop observation, exit code or\n' +
|
|
12
|
+
'producer label is never authenticated native proof, so prepare-transfer stays\n' +
|
|
13
|
+
'unavailable until an accepted host adapter produces quiescence evidence.\n\n' +
|
|
14
|
+
'Exit 0 inspected (blocked steps included, plan_complete reports completion),\n' +
|
|
15
|
+
'1 the exact record or bundle cannot support the inspection, 2 invalid request.';
|
|
16
|
+
function emitFailure(output, options, kind, code, message, nextAction, details) {
|
|
17
|
+
if (options.json) {
|
|
18
|
+
output.stdout(`${JSON.stringify({
|
|
19
|
+
schema: COLLAB_ROLLOVER_REPORT_SCHEMA,
|
|
20
|
+
action: options.action,
|
|
21
|
+
ok: false,
|
|
22
|
+
kind,
|
|
23
|
+
code,
|
|
24
|
+
message,
|
|
25
|
+
next_action: nextAction,
|
|
26
|
+
task_root: options.taskRoot,
|
|
27
|
+
request: options.requestFile,
|
|
28
|
+
details,
|
|
29
|
+
limits: [
|
|
30
|
+
'read_only_inspection',
|
|
31
|
+
'no_apply_or_mutation',
|
|
32
|
+
'host_stop_proof_unavailable',
|
|
33
|
+
'native_launch_unavailable',
|
|
34
|
+
'native_session_archive_unavailable',
|
|
35
|
+
'routing_removal_pending',
|
|
36
|
+
],
|
|
37
|
+
})}\n`);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
output.stdout(`Rollover ${options.action} rejected (${code}).\n`);
|
|
41
|
+
output.stdout(` ${message}\n`);
|
|
42
|
+
for (const detail of details)
|
|
43
|
+
output.stdout(` - ${detail}\n`);
|
|
44
|
+
if (nextAction !== null)
|
|
45
|
+
output.stdout(` next: ${nextAction}\n`);
|
|
46
|
+
}
|
|
47
|
+
return kind === 'invalid' ? 2 : 1;
|
|
48
|
+
}
|
|
49
|
+
function emitHuman(report, output) {
|
|
50
|
+
const intentLabel = report.intent.intent_id ?? '<unrecorded intent>';
|
|
51
|
+
output.stdout(`Rollover ${report.action} on task ${report.task_id} (revision ${report.state_revision}, epoch ${String(report.owner_epoch)}): intent ${intentLabel}.\n`);
|
|
52
|
+
output.stdout(` record: ${report.intent.found ? 'recorded intent' : 'proposed intent'}, handoff ${report.handoff.state ?? '<none>'}, attempt ${report.attempt?.state ?? '<none>'}\n`);
|
|
53
|
+
for (const claim of report.claims) {
|
|
54
|
+
output.stdout(` claim ${claim.claim_id}: holder ${claim.holder?.agent_id ?? '<none>'}, epoch ${String(claim.resource_epoch)} (expected ${claim.expected_resource_epoch})${claim.released_at === null ? '' : ', released'}\n`);
|
|
55
|
+
}
|
|
56
|
+
output.stdout(` bundle ${report.bundle.ref}: verified, context ${report.bundle.context_integrity}, association ${report.bundle.collaboration.matches_plan ? 'matches' : 'differs'}, execution ${String(report.bundle.execution_allowed)}\n`);
|
|
57
|
+
for (const step of report.steps) {
|
|
58
|
+
output.stdout(` ${step.step}: ${step.status}\n`);
|
|
59
|
+
for (const blocker of step.blockers)
|
|
60
|
+
output.stdout(` blocked by ${blocker.code}: ${blocker.detail}\n`);
|
|
61
|
+
}
|
|
62
|
+
if (report.drift.length > 0) {
|
|
63
|
+
output.stdout(' current-record drift:\n');
|
|
64
|
+
for (const blocker of report.drift)
|
|
65
|
+
output.stdout(` ${blocker.code}: ${blocker.detail}\n`);
|
|
66
|
+
}
|
|
67
|
+
output.stdout(` notify exclusion for the planned identities: ${report.notify_exclusion.effective}\n`);
|
|
68
|
+
if (report.evidence.requested.length > 0)
|
|
69
|
+
output.stdout(` evidence: ${report.evidence.supplied}/${report.evidence.requested.length} correlated envelope(s), ${report.evidence.raw_bytes} raw bytes\n`);
|
|
70
|
+
for (const entry of report.evidence.unreadable)
|
|
71
|
+
output.stdout(` unreadable ${entry.message_id}: ${entry.code}\n`);
|
|
72
|
+
output.stdout(` plan complete: ${String(report.plan_complete)} (host stop proof ${report.capabilities.host_stop_proof}, native launch ${report.capabilities.native_launch}, routing removal ${report.capabilities.routing_removal})\n`);
|
|
73
|
+
output.stdout(' read-only: no intent, claim, handoff, bundle, binding, notification or delivery file was written and nothing was applied.\n');
|
|
74
|
+
}
|
|
75
|
+
export async function runCollaborationRolloverCommand(options, output) {
|
|
76
|
+
const errors = [];
|
|
77
|
+
if (options.taskRoot === null)
|
|
78
|
+
errors.push('--task-root is required.');
|
|
79
|
+
else if (!path.isAbsolute(options.taskRoot))
|
|
80
|
+
errors.push('--task-root must be absolute.');
|
|
81
|
+
if (options.requestFile === null)
|
|
82
|
+
errors.push('--request is required.');
|
|
83
|
+
else if (!path.isAbsolute(options.requestFile))
|
|
84
|
+
errors.push('--request must be an absolute path to the request document.');
|
|
85
|
+
if (errors.length > 0)
|
|
86
|
+
return emitFailure(output, options, 'invalid', 'invalid_arguments', 'The rollover request is incomplete.', collaborationRolloverUsage, errors);
|
|
87
|
+
const loaded = loadRolloverRequest(options.requestFile);
|
|
88
|
+
if (loaded.ok === false)
|
|
89
|
+
return emitFailure(output, options, loaded.kind, loaded.code, loaded.message, loaded.nextAction, []);
|
|
90
|
+
const request = loaded.value;
|
|
91
|
+
if (options.action !== request.action)
|
|
92
|
+
return emitFailure(output, options, 'invalid', 'request_action_mismatch', `The command asks for ${options.action} but the request document declares ${request.action}.`, 'Use one action in both the command and the request document.', []);
|
|
93
|
+
if (path.resolve(request.task_root) !== path.resolve(options.taskRoot))
|
|
94
|
+
return emitFailure(output, options, 'invalid', 'task_root_mismatch', 'The request task_root is not the --task-root passed on the command line.', 'Use one absolute task root; the cwd is never used to infer it.', []);
|
|
95
|
+
const report = await inspectOrPlanRollover(request);
|
|
96
|
+
if (report.ok === false)
|
|
97
|
+
return emitFailure(output, options, report.kind, report.code, report.message, report.nextAction, []);
|
|
98
|
+
if (options.json)
|
|
99
|
+
output.stdout(`${JSON.stringify(report.value)}\n`);
|
|
100
|
+
else
|
|
101
|
+
emitHuman(report.value, output);
|
|
102
|
+
return 0;
|
|
103
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type StateAction } from '../../app/collab-state.js';
|
|
2
|
+
import type { CliOutput } from '../output.js';
|
|
3
|
+
export declare const collaborationStateUsage: string;
|
|
4
|
+
export interface CollaborationStateOptions {
|
|
5
|
+
readonly action: StateAction | null;
|
|
6
|
+
readonly taskRoot: string | null;
|
|
7
|
+
readonly ownerEpoch: string | null;
|
|
8
|
+
readonly json: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function runCollaborationStateCommand(options: CollaborationStateOptions, output: CliOutput): Promise<number>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { COLLAB_STATE_SCHEMA, checkTaskEpoch, doctorTaskState, showTaskState, } from '../../app/collab-state.js';
|
|
3
|
+
export const collaborationStateUsage = 'pappra collab state <show|doctor|epoch-check> --task-root <abs> [options]\n' +
|
|
4
|
+
' show --task-root <abs> [--json]\n' +
|
|
5
|
+
' doctor --task-root <abs> [--json]\n' +
|
|
6
|
+
' epoch-check --task-root <abs> --owner-epoch <positive integer> [--json]\n\n' +
|
|
7
|
+
'Read-only task-state projections over the existing record/lock/transaction\n' +
|
|
8
|
+
'primitives. Nothing is repaired, released, restarted or launched. Exit 0 ready,\n' +
|
|
9
|
+
'1 needs_input/uncertainty, 2 invalid request/options.';
|
|
10
|
+
function invalid(output, options, errors) {
|
|
11
|
+
if (options.json) {
|
|
12
|
+
output.stdout(`${JSON.stringify({
|
|
13
|
+
schema: COLLAB_STATE_SCHEMA,
|
|
14
|
+
ok: false,
|
|
15
|
+
status: 'invalid',
|
|
16
|
+
action: options.action,
|
|
17
|
+
errors,
|
|
18
|
+
})}\n`);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
output.stdout(`State request invalid.\n`);
|
|
22
|
+
for (const error of errors)
|
|
23
|
+
output.stdout(` - ${error}\n`);
|
|
24
|
+
}
|
|
25
|
+
return 2;
|
|
26
|
+
}
|
|
27
|
+
function failure(output, options, value) {
|
|
28
|
+
if (options.json) {
|
|
29
|
+
output.stdout(`${JSON.stringify({
|
|
30
|
+
schema: COLLAB_STATE_SCHEMA,
|
|
31
|
+
ok: false,
|
|
32
|
+
status: 'needs_input',
|
|
33
|
+
action: options.action,
|
|
34
|
+
code: value.code,
|
|
35
|
+
message: value.message,
|
|
36
|
+
nextAction: value.nextAction,
|
|
37
|
+
})}\n`);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
output.stdout(`State needs input: ${value.message}\n`);
|
|
41
|
+
if (value.nextAction)
|
|
42
|
+
output.stdout(` ${value.nextAction}\n`);
|
|
43
|
+
}
|
|
44
|
+
return 1;
|
|
45
|
+
}
|
|
46
|
+
function emitHuman(value, action, output) {
|
|
47
|
+
if (action === 'show') {
|
|
48
|
+
output.stdout(`Task ${String(value.task_id)} revision ${String(value.state_revision)}.\n`);
|
|
49
|
+
output.stdout(` attempts: ${String(value.counts.attempts)}; claims: ${String(value.counts.claims)}; messages: ${String(value.messages)}\n`);
|
|
50
|
+
const lock = value.lock;
|
|
51
|
+
output.stdout(` lock: ${lock.held === true ? 'held' : 'not held'}; transactions: ${String(lock.transaction_count)}\n`);
|
|
52
|
+
}
|
|
53
|
+
else if (action === 'doctor') {
|
|
54
|
+
const findings = value.findings;
|
|
55
|
+
const counts = value.counts;
|
|
56
|
+
output.stdout(`Doctor ${value.ok === true ? 'ready' : 'needs input'}: ${String(counts.findings)} finding(s), ${String(counts.blocking)} blocking, ${String(counts.uncertain)} uncertain, ${String(counts.active)} active lock observation(s).\n`);
|
|
57
|
+
for (const finding of findings)
|
|
58
|
+
output.stdout(` - ${finding.severity}: ${finding.code}\n`);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
output.stdout(`Owner epoch ${value.ok === true ? 'matches' : 'does not match'}: expected ${String(value.expected)}, actual ${String(value.actual)}.\n`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export async function runCollaborationStateCommand(options, output) {
|
|
65
|
+
if (options.action === null)
|
|
66
|
+
return invalid(output, options, [
|
|
67
|
+
'state requires show, doctor or epoch-check.',
|
|
68
|
+
]);
|
|
69
|
+
if (options.taskRoot === null)
|
|
70
|
+
return invalid(output, options, ['--task-root is required.']);
|
|
71
|
+
if (!path.isAbsolute(options.taskRoot))
|
|
72
|
+
return invalid(output, options, ['--task-root must be absolute.']);
|
|
73
|
+
let ownerEpoch = null;
|
|
74
|
+
if (options.action === 'epoch-check') {
|
|
75
|
+
if (options.ownerEpoch === null)
|
|
76
|
+
return invalid(output, options, ['epoch-check requires --owner-epoch.']);
|
|
77
|
+
const parsed = Number(options.ownerEpoch.trim());
|
|
78
|
+
if (!Number.isSafeInteger(parsed) || parsed <= 0)
|
|
79
|
+
return invalid(output, options, [
|
|
80
|
+
'--owner-epoch must be a positive integer.',
|
|
81
|
+
]);
|
|
82
|
+
ownerEpoch = parsed;
|
|
83
|
+
}
|
|
84
|
+
const result = options.action === 'show'
|
|
85
|
+
? await showTaskState(options.taskRoot)
|
|
86
|
+
: options.action === 'doctor'
|
|
87
|
+
? await doctorTaskState(options.taskRoot)
|
|
88
|
+
: await checkTaskEpoch(options.taskRoot, ownerEpoch);
|
|
89
|
+
if (!result.ok)
|
|
90
|
+
return failure(output, options, result);
|
|
91
|
+
if (options.json)
|
|
92
|
+
output.stdout(`${JSON.stringify(result.value)}\n`);
|
|
93
|
+
else
|
|
94
|
+
emitHuman(result.value, options.action, output);
|
|
95
|
+
return result.value.ok === true ? 0 : 1;
|
|
96
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type SessionTransitionAction, type SessionTransitionDependencies } from '../../app/collab-session-transition.js';
|
|
2
|
+
import type { CliOutput } from '../output.js';
|
|
3
|
+
export declare const collaborationTransitionUsage: string;
|
|
4
|
+
export interface CollaborationTransitionOptions {
|
|
5
|
+
readonly action: SessionTransitionAction | null;
|
|
6
|
+
readonly taskRoot: string | null;
|
|
7
|
+
readonly requestFile: string | null;
|
|
8
|
+
readonly json: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function runCollaborationTransitionCommand(options: CollaborationTransitionOptions, output: CliOutput, dependencies?: SessionTransitionDependencies): Promise<number>;
|
|
@@ -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>;
|