@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
package/dist/cli/commands/mcp.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { runMcpServer } from '../../mcp/server.js';
|
|
2
|
-
export const mcpUsage = 'pappra mcp [--root <dir>] [--json]\n\n' +
|
|
3
|
-
'Starts the Pappra MCP server on stdio for the selected workspace.
|
|
4
|
-
'
|
|
5
|
-
'
|
|
2
|
+
export const mcpUsage = 'pappra mcp [--root <dir>] [--allow-workspace-writes] [--json]\n\n' +
|
|
3
|
+
'Starts the Pappra MCP server on stdio for the selected workspace. stdout carries\n' +
|
|
4
|
+
'MCP JSON-RPC; use --help outside a host.\n\n' +
|
|
5
|
+
'Read-only tools: workspace_status, resume, docs_list, docs_check, code_status,\n' +
|
|
6
|
+
'code_query, runtime_status.\n' +
|
|
7
|
+
'The default server cannot mutate state, install code or launch agent/index work. A trusted host may\n' +
|
|
8
|
+
'enable checkpoint/docs_scan and workspace-private collab_prepare at server startup\n' +
|
|
9
|
+
'with --allow-workspace-writes; apply only selects preview versus execution.\n' +
|
|
10
|
+
'runtime_install and code_prepare execution always require the authorized CLI.\n' +
|
|
11
|
+
'collab_start returns cli_required and never launches, even with confirm: true.';
|
|
6
12
|
export async function runMcpCommand(options, output) {
|
|
7
13
|
const root = options.root ?? options.cwd;
|
|
8
14
|
if (options.json) {
|
|
9
15
|
output.stderr('pappra mcp: --json is not used; the server speaks MCP JSON-RPC on stdout.\n');
|
|
10
16
|
}
|
|
11
|
-
await runMcpServer(root);
|
|
17
|
+
await runMcpServer(root, options.allowWorkspaceWrites === true);
|
|
12
18
|
return 0;
|
|
13
19
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CliOutput } from '../output.js';
|
|
2
|
+
export declare const repairUsage: string;
|
|
3
|
+
export declare function runRepairCommand(options: {
|
|
4
|
+
readonly root: string;
|
|
5
|
+
readonly runtimeVersion?: string;
|
|
6
|
+
readonly installId?: string;
|
|
7
|
+
readonly apply: boolean;
|
|
8
|
+
readonly json: boolean;
|
|
9
|
+
readonly quarantineUnownedLocks?: boolean;
|
|
10
|
+
readonly resetLocal?: boolean;
|
|
11
|
+
readonly allWritersStopped?: boolean;
|
|
12
|
+
}, output: CliOutput): Promise<number>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { repairInstall } from '../../install/repair.js';
|
|
2
|
+
export const repairUsage = 'pappra repair [--root <workspace>] [--runtime-version <v>] [--install-id <uuid>] [--apply] [--quarantine-unowned-locks] [--reset-local --all-writers-stopped] [--json]\n' +
|
|
3
|
+
'Preview incomplete install journals, or explicitly recover them with --apply.\n' +
|
|
4
|
+
'Also inspect/recover provably dead knowledge and checkpoint writer locks.\n' +
|
|
5
|
+
'Runtime recovery targets the machine data directory for the selected version.\n' +
|
|
6
|
+
'Live/unknown lock owners and modified or unproven files are preserved.\n' +
|
|
7
|
+
'--quarantine-unowned-locks is an explicit operator assertion that ALL affected writers are stopped;\n' +
|
|
8
|
+
'with --apply it moves unknown lock evidence into private quarantine without claiming owner death.\n' +
|
|
9
|
+
'Never use this flag against a live or paused writer. Live verified owners are always refused.\n' +
|
|
10
|
+
'--reset-local explicitly archives all old private local state without migration; --apply also requires\n' +
|
|
11
|
+
'--all-writers-stopped. Existing bytes remain under ignored .pappra/local-archive; fresh init is separate.\n';
|
|
12
|
+
export async function runRepairCommand(options, output) {
|
|
13
|
+
const result = await repairInstall(options);
|
|
14
|
+
if (options.json)
|
|
15
|
+
output.stdout(`${JSON.stringify({ command: 'repair', ...result })}\n`);
|
|
16
|
+
else {
|
|
17
|
+
output.stdout(`State repair ${result.mode}: ${result.entries.length} incomplete install journal(s).\n`);
|
|
18
|
+
for (const entry of result.entries)
|
|
19
|
+
output.stdout(` ${entry.installId} ${entry.operation}: ${entry.status}\n`);
|
|
20
|
+
for (const file of result.locks)
|
|
21
|
+
output.stdout(`Writer lock: ${file}\n`);
|
|
22
|
+
for (const state of result.lockStates)
|
|
23
|
+
output.stdout(`Lock owner ${state.state}: ${state.file}\n`);
|
|
24
|
+
for (const file of result.preserved)
|
|
25
|
+
output.stdout(`Preserved unproven file: ${file}\n`);
|
|
26
|
+
for (const file of result.quarantined)
|
|
27
|
+
output.stdout(`Quarantined unowned lock evidence: ${file}\n`);
|
|
28
|
+
if (result.reset !== null)
|
|
29
|
+
output.stdout(`Local reset ${result.reset.status}; archive: ${result.reset.archive ?? '(none)'}\n`);
|
|
30
|
+
for (const file of result.repaired)
|
|
31
|
+
output.stdout(`Recovered: ${file}\n`);
|
|
32
|
+
for (const error of result.errors)
|
|
33
|
+
output.stderr(`pappra repair: ${error}\n`);
|
|
34
|
+
if (result.ok &&
|
|
35
|
+
result.mode === 'plan' &&
|
|
36
|
+
(result.entries.length > 0 || result.locks.length > 0)) {
|
|
37
|
+
output.stdout('Rerun with --apply to recover the listed install state.\n');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return result.ok ? 0 : 1;
|
|
41
|
+
}
|
|
@@ -2,7 +2,7 @@ import type { CliOutput } from '../output.js';
|
|
|
2
2
|
export declare const runtimeUsage: string;
|
|
3
3
|
export interface RuntimeCommandOptions {
|
|
4
4
|
readonly cwd: string;
|
|
5
|
-
readonly action: 'install' | 'status' | 'verify' | 'remove' | null;
|
|
5
|
+
readonly action: 'install' | 'status' | 'verify' | 'remove' | 'gc' | null;
|
|
6
6
|
readonly json: boolean;
|
|
7
7
|
readonly from: 'self' | 'tarball' | 'registry' | null;
|
|
8
8
|
readonly tarball: string | null;
|
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
import { resolve } from 'node:path';
|
|
1
|
+
import { join, resolve } from 'node:path';
|
|
2
|
+
import { readdir } from 'node:fs/promises';
|
|
3
|
+
import { inspectRuntimeReferences, runtimeBindingMatches, } from '../../install/references.js';
|
|
2
4
|
import { getPackageInfo, getPackageRoot } from '../../package-info.js';
|
|
3
5
|
import { inspectRuntimeState, inspectRuntimeStatePassive, installRuntime, removeRuntime, resolveUserDataDir, runtimePaths, } from '../../install/runtime.js';
|
|
4
6
|
import { updateMachineRuntime } from '../../install/apply.js';
|
|
5
7
|
import { inspectMachineConfig } from '../../workspace/config.js';
|
|
6
8
|
import { resolveWorkspaceRoot } from '../../workspace/resolve.js';
|
|
7
|
-
export const runtimeUsage = 'pappra runtime <install|status|verify|remove> [options] [--json]\n' +
|
|
9
|
+
export const runtimeUsage = 'pappra runtime <install|status|verify|remove|gc> [options] [--json]\n' +
|
|
8
10
|
' install [--from self|tarball|registry] [--tarball <file>] [--runtime-version <v>]\n' +
|
|
9
11
|
' [--apply] [--bind]\n' +
|
|
10
12
|
' status\n' +
|
|
11
13
|
' verify [--runtime-version <v>]\n' +
|
|
12
|
-
' remove [--runtime-version <v>] --apply [--force]\n
|
|
14
|
+
' remove [--runtime-version <v>] [--apply] [--force]\n' +
|
|
15
|
+
' gc [--runtime-version <v>] [--apply] [--force]\n\n' +
|
|
13
16
|
'Install keeps a durable copy of the package outside the checkout. --from self packs the\n' +
|
|
14
17
|
'package that is currently executing, which is what makes an npx/dlx bootstrap survive\n' +
|
|
15
|
-
'cache eviction. Writes require --apply; --bind records the copy in machine.json.\n'
|
|
18
|
+
'cache eviction. Writes require --apply; --bind records the copy in machine.json.\n' +
|
|
19
|
+
'Only explicitly registered workspace roots are inspected; no home scan is performed.\n' +
|
|
20
|
+
'--force accepts unknown/unregistered coverage, but never bypasses a verified workspace binding.\n';
|
|
16
21
|
async function inspectBinding(cwd) {
|
|
17
22
|
const resolution = await resolveWorkspaceRoot({ startPath: cwd });
|
|
18
23
|
if (resolution.root === null)
|
|
@@ -197,53 +202,147 @@ async function runVerify(options, output, binding) {
|
|
|
197
202
|
async function runRemove(options, output, binding) {
|
|
198
203
|
const version = options.version ?? binding?.runtime?.version ?? null;
|
|
199
204
|
if (version === null) {
|
|
200
|
-
|
|
205
|
+
const message = 'runtime remove requires --runtime-version.';
|
|
206
|
+
if (options.json)
|
|
207
|
+
output.stdout(`${JSON.stringify({ ok: false, code: 'invalid_arguments', message })}\n`);
|
|
208
|
+
else
|
|
209
|
+
output.stderr(`pappra: ${message}\n`);
|
|
201
210
|
return 2;
|
|
202
211
|
}
|
|
212
|
+
const dataDir = resolveUserDataDir();
|
|
213
|
+
const boundHere = await runtimeBindingMatches(dataDir, version, binding?.runtime);
|
|
214
|
+
const references = await inspectRuntimeReferences(dataDir, version);
|
|
203
215
|
if (!options.apply) {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
const boundHere = binding?.runtime?.version === version;
|
|
208
|
-
if (boundHere && !options.force) {
|
|
209
|
-
const message = 'machine.json still binds this runtime; pass --force to remove it anyway.';
|
|
210
|
-
if (options.json) {
|
|
211
|
-
output.stdout(`${JSON.stringify({
|
|
212
|
-
ok: false,
|
|
213
|
-
command: 'runtime',
|
|
214
|
-
action: 'remove',
|
|
215
|
-
version,
|
|
216
|
-
message,
|
|
217
|
-
})}\n`);
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
output.stderr(`pappra runtime remove: ${message}\n`);
|
|
221
|
-
}
|
|
222
|
-
return 1;
|
|
223
|
-
}
|
|
224
|
-
const removed = await removeRuntime({
|
|
225
|
-
version,
|
|
226
|
-
dataDir: resolveUserDataDir(),
|
|
227
|
-
// The current workspace was already checked above; callers that need to
|
|
228
|
-
// protect other checkouts pass --force only after checking them.
|
|
229
|
-
activeReferences: [],
|
|
230
|
-
});
|
|
231
|
-
if (options.json) {
|
|
232
|
-
output.stdout(`${JSON.stringify({
|
|
233
|
-
ok: removed.ok,
|
|
216
|
+
const plan = {
|
|
217
|
+
ok: true,
|
|
234
218
|
command: 'runtime',
|
|
235
219
|
action: 'remove',
|
|
220
|
+
mode: 'plan',
|
|
236
221
|
version,
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
222
|
+
runtimeRoot: runtimePaths(version, dataDir).runtimeRoot,
|
|
223
|
+
references,
|
|
224
|
+
boundHere,
|
|
225
|
+
eligibleUnderForcePolicy: !boundHere && references.active.length === 0 && options.force,
|
|
226
|
+
nextAction: 'Use --apply after review. --force accepts unknown coverage only; active bindings are always retained.',
|
|
227
|
+
};
|
|
228
|
+
output.stdout(options.json
|
|
229
|
+
? `${JSON.stringify(plan)}\n`
|
|
230
|
+
: `Runtime removal plan ${version}: ${boundHere || references.active.length > 0 ? 'referenced; retained' : 'global coverage unknown; explicit --force required'}.\n`);
|
|
231
|
+
return 0;
|
|
240
232
|
}
|
|
233
|
+
const removed = await removeRuntime({
|
|
234
|
+
version,
|
|
235
|
+
dataDir,
|
|
236
|
+
...(boundHere && binding !== null
|
|
237
|
+
? { activeReferences: [binding.root] }
|
|
238
|
+
: {}),
|
|
239
|
+
forceUnknownReferences: options.force,
|
|
240
|
+
});
|
|
241
|
+
if (options.json)
|
|
242
|
+
output.stdout(`${JSON.stringify({ ok: removed.ok, command: 'runtime', action: 'remove', version, removed, references, machineBindingRetained: boundHere })}\n`);
|
|
241
243
|
else {
|
|
242
244
|
output.stdout(`Runtime ${version}: ${removed.status}\n`);
|
|
243
245
|
printDiagnostics(output, removed.diagnostics);
|
|
244
246
|
}
|
|
245
247
|
return removed.ok ? 0 : 1;
|
|
246
248
|
}
|
|
249
|
+
async function runGc(options, output, binding) {
|
|
250
|
+
if (options.version !== null &&
|
|
251
|
+
!/^[0-9A-Za-z][0-9A-Za-z0-9._+-]*$/.test(options.version)) {
|
|
252
|
+
const message = 'runtime gc requires an exact --runtime-version without path separators.';
|
|
253
|
+
output.stdout(options.json
|
|
254
|
+
? `${JSON.stringify({ ok: false, code: 'invalid_arguments', message })}\n`
|
|
255
|
+
: `${message}\n`);
|
|
256
|
+
return 2;
|
|
257
|
+
}
|
|
258
|
+
if (options.from !== null || options.tarball !== null || options.bind) {
|
|
259
|
+
const message = 'runtime gc accepts only --runtime-version, --apply, --force and --json.';
|
|
260
|
+
if (options.json)
|
|
261
|
+
output.stdout(`${JSON.stringify({ ok: false, code: 'invalid_arguments', message })}\n`);
|
|
262
|
+
else
|
|
263
|
+
output.stderr(`${message}\n`);
|
|
264
|
+
return 2;
|
|
265
|
+
}
|
|
266
|
+
const dataDir = resolveUserDataDir();
|
|
267
|
+
let versions;
|
|
268
|
+
try {
|
|
269
|
+
const entries = await readdir(join(dataDir, 'runtimes'), {
|
|
270
|
+
withFileTypes: true,
|
|
271
|
+
});
|
|
272
|
+
versions = entries
|
|
273
|
+
.filter((entry) => entry.isDirectory() &&
|
|
274
|
+
/^[0-9A-Za-z][0-9A-Za-z0-9._+-]*$/.test(entry.name))
|
|
275
|
+
.map((entry) => entry.name)
|
|
276
|
+
.sort();
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
if (error.code !== 'ENOENT') {
|
|
280
|
+
const report = {
|
|
281
|
+
ok: false,
|
|
282
|
+
command: 'runtime',
|
|
283
|
+
action: 'gc',
|
|
284
|
+
mode: options.apply ? 'apply' : 'plan',
|
|
285
|
+
message: 'Runtime directory is unreadable; nothing was removed.',
|
|
286
|
+
};
|
|
287
|
+
output.stdout(options.json ? `${JSON.stringify(report)}\n` : `${report.message}\n`);
|
|
288
|
+
return 1;
|
|
289
|
+
}
|
|
290
|
+
versions = [];
|
|
291
|
+
}
|
|
292
|
+
if (options.version !== null)
|
|
293
|
+
versions = versions.filter((version) => version === options.version);
|
|
294
|
+
if (versions.length > 256) {
|
|
295
|
+
const message = 'Runtime GC version limit exceeded; select one --runtime-version.';
|
|
296
|
+
output.stdout(options.json
|
|
297
|
+
? `${JSON.stringify({ ok: false, command: 'runtime', action: 'gc', message })}\n`
|
|
298
|
+
: `${message}\n`);
|
|
299
|
+
return 1;
|
|
300
|
+
}
|
|
301
|
+
const entries = [];
|
|
302
|
+
let ok = true;
|
|
303
|
+
for (const version of versions) {
|
|
304
|
+
const references = await inspectRuntimeReferences(dataDir, version);
|
|
305
|
+
const boundHere = await runtimeBindingMatches(dataDir, version, binding?.runtime);
|
|
306
|
+
if (boundHere || references.active.length > 0) {
|
|
307
|
+
entries.push({
|
|
308
|
+
version,
|
|
309
|
+
status: 'retained',
|
|
310
|
+
reason: 'verified-workspace-reference',
|
|
311
|
+
references,
|
|
312
|
+
});
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
if (!options.apply) {
|
|
316
|
+
entries.push({
|
|
317
|
+
version,
|
|
318
|
+
status: options.force ? 'candidate' : 'unknown',
|
|
319
|
+
references,
|
|
320
|
+
});
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
const removed = await removeRuntime({
|
|
324
|
+
version,
|
|
325
|
+
dataDir,
|
|
326
|
+
forceUnknownReferences: options.force,
|
|
327
|
+
});
|
|
328
|
+
entries.push({ version, ...removed, references });
|
|
329
|
+
ok &&= removed.ok;
|
|
330
|
+
}
|
|
331
|
+
const report = {
|
|
332
|
+
ok,
|
|
333
|
+
command: 'runtime',
|
|
334
|
+
action: 'gc',
|
|
335
|
+
mode: options.apply ? 'apply' : 'plan',
|
|
336
|
+
dataDir,
|
|
337
|
+
coverage: 'registered-workspaces-only',
|
|
338
|
+
unregisteredCoverage: 'unknown',
|
|
339
|
+
entries,
|
|
340
|
+
};
|
|
341
|
+
output.stdout(options.json
|
|
342
|
+
? `${JSON.stringify(report)}\n`
|
|
343
|
+
: `Runtime GC ${report.mode}: ${entries.map((entry) => `${String(entry['version'])}=${String(entry['status'])}`).join(', ') || 'no versions'}\n`);
|
|
344
|
+
return ok ? 0 : 1;
|
|
345
|
+
}
|
|
247
346
|
export async function runRuntimeCommand(options, output) {
|
|
248
347
|
if (options.action === null) {
|
|
249
348
|
output.stderr(`${runtimeUsage}`);
|
|
@@ -259,5 +358,7 @@ export async function runRuntimeCommand(options, output) {
|
|
|
259
358
|
return runVerify(options, output, binding);
|
|
260
359
|
case 'remove':
|
|
261
360
|
return runRemove(options, output, binding);
|
|
361
|
+
case 'gc':
|
|
362
|
+
return runGc(options, output, binding);
|
|
262
363
|
}
|
|
263
364
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CliOutput } from '../output.js';
|
|
2
|
+
export declare const sessionUsage: string;
|
|
3
|
+
export declare function runSessionCommand(options: {
|
|
4
|
+
readonly action: string;
|
|
5
|
+
readonly config: string | null;
|
|
6
|
+
readonly json: boolean;
|
|
7
|
+
}, output: CliOutput): Promise<number>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { readManagedPiRequest, planManagedPiSession, } from '../../app/managed-pi.js';
|
|
2
|
+
import { startManagedPiSession, requestManagedPiControl, } from '../../hosts/pi/managed-session.js';
|
|
3
|
+
import { watchManagedPiReadiness } from '../../app/managed-pi-readiness.js';
|
|
4
|
+
import { runManagedPiSdkRuntime } from '../../app/managed-pi-sdk-runtime.js';
|
|
5
|
+
export const sessionUsage = 'pappra session <plan|start|status|fence|stop> --config <abs managed-pi.json> [--json]\n\n' +
|
|
6
|
+
'plan validates a launch request without effects. start requires a visible terminal,\n' +
|
|
7
|
+
'launches native Pi TUI with OpenRouter and preserves daily configuration.\n' +
|
|
8
|
+
'Ingress is journaled; exact-child exit is separate from transfer-safe quiescence.\n' +
|
|
9
|
+
'status/fence/stop address only the private endpoint created by that launch.\n' +
|
|
10
|
+
'No existing interactive session is adopted. start does not accept --json.';
|
|
11
|
+
export async function runSessionCommand(options, output) {
|
|
12
|
+
try {
|
|
13
|
+
if (options.config === null)
|
|
14
|
+
throw new Error('--config is required.');
|
|
15
|
+
const request = readManagedPiRequest(options.config);
|
|
16
|
+
if (options.action === 'status' ||
|
|
17
|
+
options.action === 'fence' ||
|
|
18
|
+
options.action === 'stop') {
|
|
19
|
+
const result = await requestManagedPiControl(`${request.journalPath}.control.json`, options.action === 'status' ? 'snapshot' : options.action);
|
|
20
|
+
output.stdout(`${JSON.stringify(result, null, options.json ? undefined : 2)}\n`);
|
|
21
|
+
if (options.action === 'stop') {
|
|
22
|
+
const exit = result.exit;
|
|
23
|
+
return result.ok === true &&
|
|
24
|
+
typeof exit === 'object' &&
|
|
25
|
+
exit !== null &&
|
|
26
|
+
'status' in exit &&
|
|
27
|
+
(exit.status === 'exited' || exit.status === 'runtime_disposed')
|
|
28
|
+
? 0
|
|
29
|
+
: 1;
|
|
30
|
+
}
|
|
31
|
+
return result.ok === true ? 0 : 1;
|
|
32
|
+
}
|
|
33
|
+
if (options.action === 'plan') {
|
|
34
|
+
output.stdout(`${JSON.stringify(planManagedPiSession(request), null, options.json ? undefined : 2)}\n`);
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
if (options.action !== 'start')
|
|
38
|
+
throw new Error('session accepts plan, start, status, fence or stop.');
|
|
39
|
+
if (options.json)
|
|
40
|
+
throw new Error('Native TUI start does not accept --json.');
|
|
41
|
+
if (request.runtime === 'sdk') {
|
|
42
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY)
|
|
43
|
+
throw new Error('SDK mode requires a visible native terminal.');
|
|
44
|
+
return await runManagedPiSdkRuntime(request);
|
|
45
|
+
}
|
|
46
|
+
const { schema: _schema, readiness, ...launch } = request;
|
|
47
|
+
const session = await startManagedPiSession(launch);
|
|
48
|
+
let publisher = null;
|
|
49
|
+
try {
|
|
50
|
+
if (readiness)
|
|
51
|
+
publisher = watchManagedPiReadiness(readiness, {
|
|
52
|
+
sessionId: session.identity.sessionId,
|
|
53
|
+
cwd: launch.cwd,
|
|
54
|
+
metadataFile: `${launch.journalPath}.pi-events.jsonl`,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Readiness failure does not terminate an otherwise owned, visible session.
|
|
59
|
+
output.stderr('Readiness watcher could not start; task preflight remains required.\n');
|
|
60
|
+
}
|
|
61
|
+
const exit = await session.waitForExit().finally(() => publisher?.close());
|
|
62
|
+
if (exit.status === 'exited')
|
|
63
|
+
session.close();
|
|
64
|
+
if (exit.status !== 'exited') {
|
|
65
|
+
output.stderr('Managed Pi child exit is unknown; inspect retained controller evidence.\n');
|
|
66
|
+
return 1;
|
|
67
|
+
}
|
|
68
|
+
return exit.exitCode === 0 ? 0 : 1;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
const result = {
|
|
72
|
+
ok: false,
|
|
73
|
+
code: 'managed_pi_session_refused',
|
|
74
|
+
message: error instanceof Error ? error.message : 'Managed Pi session failed.',
|
|
75
|
+
};
|
|
76
|
+
if (options.json)
|
|
77
|
+
output.stdout(`${JSON.stringify(result)}\n`);
|
|
78
|
+
else
|
|
79
|
+
output.stderr(`${result.message}\n`);
|
|
80
|
+
return 2;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { resolveWorkspaceRoot } from '../../workspace/resolve.js';
|
|
2
2
|
import { pinTask, readAutoResume, readTaskPin, setAutoResume, unpinTask, } from '../../app/task-pin.js';
|
|
3
|
+
import { loadWorkspaceConfig } from '../../workspace/config.js';
|
|
3
4
|
export const taskUsage = 'pappra task <pin|unpin|show> [taskId] [--auto-resume] [--json]\n\n' +
|
|
4
5
|
'pin records the current task in .pappra/local/current-task. Hooks inject a resume\n' +
|
|
5
|
-
|
|
6
|
+
"packet only when this checkout's private auto-resume preference is on (--auto-resume).\n" +
|
|
7
|
+
'The preference lives in .pappra/local/task-preferences.json and never rewrites workspace.json.';
|
|
6
8
|
function failure(output, options, message) {
|
|
7
9
|
if (options.json) {
|
|
8
10
|
output.stdout(`${JSON.stringify({ ok: false, code: 'task_invalid', message })}\n`);
|
|
@@ -15,8 +17,17 @@ function failure(output, options, message) {
|
|
|
15
17
|
export async function runTaskCommand(options, output) {
|
|
16
18
|
const resolution = await resolveWorkspaceRoot({ startPath: options.cwd });
|
|
17
19
|
const root = resolution.root;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
const mutating = options.action === 'pin' || options.action === 'unpin';
|
|
21
|
+
if (root === null || (mutating && resolution.state !== 'registered')) {
|
|
22
|
+
return failure(output, options, `task requires a registered Pappra workspace above the current directory (found: ${resolution.state}).`);
|
|
23
|
+
}
|
|
24
|
+
if (mutating) {
|
|
25
|
+
// An incomplete or unsafe registration can still report a root; mutations
|
|
26
|
+
// also require configuration this version can read.
|
|
27
|
+
const config = await loadWorkspaceConfig(root);
|
|
28
|
+
if (!config.ok) {
|
|
29
|
+
return failure(output, options, `workspace configuration is not usable: ${config.message}`);
|
|
30
|
+
}
|
|
20
31
|
}
|
|
21
32
|
if (options.action === 'pin') {
|
|
22
33
|
if (options.taskId === null) {
|
|
@@ -29,7 +40,7 @@ export async function runTaskCommand(options, output) {
|
|
|
29
40
|
if (options.autoResume) {
|
|
30
41
|
const switched = await setAutoResume(root, true);
|
|
31
42
|
if ('message' in switched) {
|
|
32
|
-
return failure(output, options, switched.message);
|
|
43
|
+
return failure(output, options, `task ${pinned.taskId} is pinned, but autoResume was not enabled: ${switched.message}`);
|
|
33
44
|
}
|
|
34
45
|
}
|
|
35
46
|
const report = {
|
|
@@ -44,7 +55,10 @@ export async function runTaskCommand(options, output) {
|
|
|
44
55
|
return 0;
|
|
45
56
|
}
|
|
46
57
|
if (options.action === 'unpin') {
|
|
47
|
-
await unpinTask(root);
|
|
58
|
+
const unpinned = await unpinTask(root);
|
|
59
|
+
if ('message' in unpinned) {
|
|
60
|
+
return failure(output, options, unpinned.message);
|
|
61
|
+
}
|
|
48
62
|
const report = { ok: true, action: 'unpin' };
|
|
49
63
|
output.stdout(options.json
|
|
50
64
|
? `${JSON.stringify(report)}\n`
|