pageship 0.5.0 → 0.6.0
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 +1 -1
- package/dist/cli.mjs +247 -95
- package/dist/skills/pageship/SKILL.md +13 -2
- package/dist/skills/pageship/references/viewers.md +2 -2
- package/dist/skills/pageship-chart/SKILL.md +1 -1
- package/dist/skills/pageship-code-block/SKILL.md +1 -1
- package/dist/skills/pageship-decision-record/SKILL.md +1 -1
- package/dist/skills/pageship-diagram/SKILL.md +1 -1
- package/dist/skills/pageship-docs/SKILL.md +1 -1
- package/dist/skills/pageship-explainer/SKILL.md +1 -1
- package/dist/skills/pageship-interaction/SKILL.md +1 -1
- package/dist/skills/pageship-key-figures/SKILL.md +1 -1
- package/dist/skills/pageship-media/SKILL.md +1 -1
- package/dist/skills/pageship-motion/SKILL.md +1 -1
- package/dist/skills/pageship-plan/SKILL.md +1 -1
- package/dist/skills/pageship-report/SKILL.md +1 -1
- package/dist/skills/pageship-review-report/SKILL.md +1 -1
- package/dist/skills/pageship-slide-deck/SKILL.md +1 -1
- package/dist/skills/pageship-spec/SKILL.md +1 -1
- package/dist/skills/pageship-table/SKILL.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ pnpm add -g pageship
|
|
|
14
14
|
bun add -g pageship
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
Then run `pageship --version` to check that the shell finds it. To have an agent install the CLI and the Pageship skills and sign you in, give it the [setup guide](https://pageship.dev/setup-guide) instead.
|
|
17
|
+
Then run `pageship --version` to check that the shell finds it. Run `pageship update` later to update it with the same package manager. To have an agent install the CLI and the Pageship skills and sign you in, give it the [setup guide](https://pageship.dev/setup-guide) instead.
|
|
18
18
|
|
|
19
19
|
## Get started
|
|
20
20
|
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { execFile } from "node:child_process";
|
|
2
|
+
import { exec, execFile, spawn } from "node:child_process";
|
|
3
3
|
import { access, cp, lstat, mkdir, open, readFile, readdir, readlink, realpath, rename, rm, stat, symlink, writeFile } from "node:fs/promises";
|
|
4
4
|
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
5
5
|
import { createInterface } from "node:readline/promises";
|
|
@@ -675,30 +675,18 @@ const documentsRestore = (options) => (options.client ?? client).post({
|
|
|
675
675
|
...options.headers
|
|
676
676
|
}
|
|
677
677
|
});
|
|
678
|
-
const documentsUpdateVisibility = (options) => (options.client ?? client).patch({
|
|
679
|
-
url: "/api/v1/documents/{id}/visibility",
|
|
680
|
-
...options,
|
|
681
|
-
headers: {
|
|
682
|
-
"Content-Type": "application/json",
|
|
683
|
-
...options.headers
|
|
684
|
-
}
|
|
685
|
-
});
|
|
686
678
|
const viewersList = (options) => (options.client ?? client).get({
|
|
687
679
|
url: "/api/v1/documents/{id}/viewers",
|
|
688
680
|
...options
|
|
689
681
|
});
|
|
690
|
-
const
|
|
691
|
-
url: "/api/v1/documents/{id}/
|
|
682
|
+
const viewersUpdateSharing = (options) => (options.client ?? client).patch({
|
|
683
|
+
url: "/api/v1/documents/{id}/sharing",
|
|
692
684
|
...options,
|
|
693
685
|
headers: {
|
|
694
686
|
"Content-Type": "application/json",
|
|
695
687
|
...options.headers
|
|
696
688
|
}
|
|
697
689
|
});
|
|
698
|
-
const viewersRemove = (options) => (options.client ?? client).delete({
|
|
699
|
-
url: "/api/v1/documents/{id}/viewers/{githubAccountId}",
|
|
700
|
-
...options
|
|
701
|
-
});
|
|
702
690
|
const githubGetUser = (options) => (options.client ?? client).get({
|
|
703
691
|
url: "/api/v1/github/users/{login}",
|
|
704
692
|
...options
|
|
@@ -797,10 +785,12 @@ function validRevision(value, documentId) {
|
|
|
797
785
|
var DocumentRequestError = class extends Error {
|
|
798
786
|
status;
|
|
799
787
|
httpStatus;
|
|
800
|
-
|
|
788
|
+
account;
|
|
789
|
+
constructor(status, message, httpStatus, account) {
|
|
801
790
|
super(message);
|
|
802
791
|
this.status = status;
|
|
803
792
|
this.httpStatus = httpStatus;
|
|
793
|
+
this.account = account;
|
|
804
794
|
}
|
|
805
795
|
};
|
|
806
796
|
function failed(response, error) {
|
|
@@ -921,29 +911,6 @@ async function restoreDocumentRevision(baseUrl, id, input, options = {}) {
|
|
|
921
911
|
if (record(data) && data.status === "idempotency_conflict") return { status: "idempotency_conflict" };
|
|
922
912
|
throw new Error("Invalid document restoration response. Retry with the same idempotency key.");
|
|
923
913
|
}
|
|
924
|
-
async function updateDocumentVisibility(baseUrl, id, visibility, options = {}) {
|
|
925
|
-
const { data: received, response, error } = await documentsUpdateVisibility({
|
|
926
|
-
...changeOptions(baseUrl, options),
|
|
927
|
-
path: { id },
|
|
928
|
-
body: { visibility }
|
|
929
|
-
});
|
|
930
|
-
if (!response?.ok) {
|
|
931
|
-
if (response?.status === 400) throw new DocumentRequestError("invalid_visibility", "Choose private or public.", 400);
|
|
932
|
-
if (response?.status === 401) throw new DocumentRequestError("signed_out", "Sign in to update this document.", 401);
|
|
933
|
-
if (response?.status === 403) throw new DocumentRequestError("uninvited", "Access unavailable.", 403);
|
|
934
|
-
if (response?.status === 404) throw new DocumentRequestError("unavailable", "Document unavailable.", 404);
|
|
935
|
-
throw new Error("Could not update document visibility. Try again.", { cause: error });
|
|
936
|
-
}
|
|
937
|
-
const data = received;
|
|
938
|
-
const updated = record(data) && data.status === "visibility_updated" ? normalizeDocument(data.document) : void 0;
|
|
939
|
-
const removedViewers = record(data) && data.removedViewers !== void 0 ? data.removedViewers : 0;
|
|
940
|
-
if (updated?.visibility === visibility && typeof removedViewers === "number" && Number.isSafeInteger(removedViewers) && removedViewers >= 0) return {
|
|
941
|
-
status: "visibility_updated",
|
|
942
|
-
document: updated,
|
|
943
|
-
removedViewers
|
|
944
|
-
};
|
|
945
|
-
throw new Error("Invalid document visibility response.");
|
|
946
|
-
}
|
|
947
914
|
async function publishDocument(baseUrl, input, options = {}) {
|
|
948
915
|
if (input.action) {
|
|
949
916
|
if (!(await getDocumentLimits(baseUrl, options)).publicationActions.includes(input.action)) throw new DocumentRequestError("publication_action_unsupported", "This server does not support explicit publication actions. Ask the operator to update the server. No HTML was uploaded.", 400);
|
|
@@ -1014,13 +981,14 @@ const viewerRefusals = {
|
|
|
1014
981
|
owner_account: "You already have access to your own document.",
|
|
1015
982
|
github_sign_in_required: "GitHub refused your sign-in. Sign in to Pageship again.",
|
|
1016
983
|
github_rate_limited: "GitHub is limiting requests. Try again in a minute.",
|
|
1017
|
-
github_unavailable: "GitHub is unavailable. Try again."
|
|
984
|
+
github_unavailable: "GitHub is unavailable. Try again.",
|
|
985
|
+
invalid_sharing: "A change can't both add and remove the same account."
|
|
1018
986
|
};
|
|
1019
987
|
function isViewerRefusal(value) {
|
|
1020
988
|
return typeof value === "string" && Object.hasOwn(viewerRefusals, value);
|
|
1021
989
|
}
|
|
1022
990
|
function viewerFailed(response, error) {
|
|
1023
|
-
if (response && record(error) && isViewerRefusal(error.status)) throw new DocumentRequestError(error.status, viewerRefusals[error.status], response.status);
|
|
991
|
+
if (response && record(error) && isViewerRefusal(error.status)) throw new DocumentRequestError(error.status, validUserMatch(error.account) && typeof error.message === "string" ? error.message : viewerRefusals[error.status], response.status, validUserMatch(error.account) ? error.account : void 0);
|
|
1024
992
|
failed(response, error);
|
|
1025
993
|
}
|
|
1026
994
|
async function getDocumentViewers(baseUrl, id, options = {}) {
|
|
@@ -1032,32 +1000,35 @@ async function getDocumentViewers(baseUrl, id, options = {}) {
|
|
|
1032
1000
|
if (data?.status === "listed" && Array.isArray(data.viewers) && data.viewers.every(validViewer)) return data;
|
|
1033
1001
|
throw new Error("Invalid document viewer listing response.");
|
|
1034
1002
|
}
|
|
1035
|
-
/**
|
|
1036
|
-
|
|
1037
|
-
|
|
1003
|
+
/**
|
|
1004
|
+
* The most accounts one sharing change adds and removes. The contract's DocumentSharingChange
|
|
1005
|
+
* refuses more; tests/document-contract.test.ts keeps the two equal.
|
|
1006
|
+
*/
|
|
1007
|
+
const sharingLimits = {
|
|
1008
|
+
add: 20,
|
|
1009
|
+
remove: 50
|
|
1010
|
+
};
|
|
1011
|
+
/**
|
|
1012
|
+
* Changes visibility and viewers together or not at all. The server looks up each added account
|
|
1013
|
+
* that isn't a viewer yet, as addDocumentViewer does.
|
|
1014
|
+
*/
|
|
1015
|
+
async function updateDocumentSharing(baseUrl, id, change, options = {}) {
|
|
1016
|
+
const { data, response, error } = await viewersUpdateSharing({
|
|
1038
1017
|
...changeOptions(baseUrl, options),
|
|
1039
1018
|
path: { id },
|
|
1040
|
-
body:
|
|
1041
|
-
githubAccountId: user.githubAccountId,
|
|
1042
|
-
login: user.login
|
|
1043
|
-
}
|
|
1044
|
-
});
|
|
1045
|
-
if (!response?.ok) viewerFailed(response, error);
|
|
1046
|
-
if (data?.status === "added" && validViewer(data.viewer) && data.viewer.githubAccountId === user.githubAccountId) return data;
|
|
1047
|
-
throw new Error("Invalid document viewer response.");
|
|
1048
|
-
}
|
|
1049
|
-
/** Removing an account that isn't a viewer succeeds. */
|
|
1050
|
-
async function removeDocumentViewer(baseUrl, id, githubAccountId, options = {}) {
|
|
1051
|
-
const { data, response, error } = await viewersRemove({
|
|
1052
|
-
...changeOptions(baseUrl, options),
|
|
1053
|
-
path: {
|
|
1054
|
-
id,
|
|
1055
|
-
githubAccountId
|
|
1056
|
-
}
|
|
1019
|
+
body: change
|
|
1057
1020
|
});
|
|
1058
1021
|
if (!response?.ok) viewerFailed(response, error);
|
|
1059
|
-
|
|
1060
|
-
|
|
1022
|
+
const document = data?.status === "sharing_updated" ? normalizeDocument(data.document) : void 0;
|
|
1023
|
+
if (data && document && (change.visibility === void 0 || document.visibility === change.visibility) && [
|
|
1024
|
+
data.viewers,
|
|
1025
|
+
data.added,
|
|
1026
|
+
data.removed
|
|
1027
|
+
].every((list) => Array.isArray(list) && list.every(validViewer))) return {
|
|
1028
|
+
...data,
|
|
1029
|
+
document
|
|
1030
|
+
};
|
|
1031
|
+
throw new Error("Invalid document sharing response.");
|
|
1061
1032
|
}
|
|
1062
1033
|
async function getGitHubUser(baseUrl, login, options = {}) {
|
|
1063
1034
|
const { data, response, error } = await githubGetUser({
|
|
@@ -1448,6 +1419,8 @@ const outcomes = {
|
|
|
1448
1419
|
restored: "succeeded",
|
|
1449
1420
|
viewers_updated: "succeeded",
|
|
1450
1421
|
skills_installed: "succeeded",
|
|
1422
|
+
cli_updated: "succeeded",
|
|
1423
|
+
cli_current: "succeeded",
|
|
1451
1424
|
authorization_pending: "pending",
|
|
1452
1425
|
expired: "pending",
|
|
1453
1426
|
signed_out: "pending",
|
|
@@ -1483,6 +1456,8 @@ const outcomes = {
|
|
|
1483
1456
|
document_id_taken: "failed",
|
|
1484
1457
|
publication_action_unsupported: "failed",
|
|
1485
1458
|
skills_modified: "failed",
|
|
1459
|
+
install_unknown: "failed",
|
|
1460
|
+
update_failed: "failed",
|
|
1486
1461
|
ambiguous_viewer: "failed",
|
|
1487
1462
|
document_public: "failed",
|
|
1488
1463
|
github_user_not_found: "failed",
|
|
@@ -1504,7 +1479,8 @@ const commandNames = [
|
|
|
1504
1479
|
"visibility",
|
|
1505
1480
|
"viewers",
|
|
1506
1481
|
"restore",
|
|
1507
|
-
"skills"
|
|
1482
|
+
"skills",
|
|
1483
|
+
"update"
|
|
1508
1484
|
];
|
|
1509
1485
|
const isCommandName = (value) => commandNames.some((name) => name === value);
|
|
1510
1486
|
/** Exit codes follow the outcome, except an interruption, which exits 130. */
|
|
@@ -1554,7 +1530,7 @@ function commandLine(command, args) {
|
|
|
1554
1530
|
}
|
|
1555
1531
|
//#endregion
|
|
1556
1532
|
//#region package.json
|
|
1557
|
-
var version = "0.
|
|
1533
|
+
var version = "0.6.0";
|
|
1558
1534
|
//#endregion
|
|
1559
1535
|
//#region src/publish.ts
|
|
1560
1536
|
const execute = promisify(execFile);
|
|
@@ -2427,10 +2403,12 @@ function downloadDocument(options) {
|
|
|
2427
2403
|
}
|
|
2428
2404
|
function changeVisibility(options) {
|
|
2429
2405
|
return asOwner(options.server, options.signal, async ({ origin }, request) => {
|
|
2430
|
-
const
|
|
2431
|
-
const
|
|
2406
|
+
const { document, removed } = await updateDocumentSharing(origin, options.documentId, { visibility: options.visibility }, request);
|
|
2407
|
+
const removedViewers = removed.length;
|
|
2432
2408
|
return {
|
|
2433
|
-
|
|
2409
|
+
status: "visibility_updated",
|
|
2410
|
+
document,
|
|
2411
|
+
removedViewers,
|
|
2434
2412
|
message: document.visibility === "public" ? `${document.id} is public.${removedViewers ? ` Removed its ${viewerCount(removedViewers)}.` : ""} Anyone with the URL can read its current revision: ${document.url}` : `${document.id} is private. Only you and its ${document.sharedWith ? viewerCount(document.sharedWith) : "viewers"} can read it after signing in: ${document.url}`
|
|
2435
2413
|
};
|
|
2436
2414
|
});
|
|
@@ -2510,6 +2488,10 @@ const installNext = {
|
|
|
2510
2488
|
command: "skills",
|
|
2511
2489
|
args: ["install"]
|
|
2512
2490
|
};
|
|
2491
|
+
const updateNext = {
|
|
2492
|
+
command: "update",
|
|
2493
|
+
args: []
|
|
2494
|
+
};
|
|
2513
2495
|
/** The output of `node --version` from PATH, or undefined when it does not run. */
|
|
2514
2496
|
const nodeOnPath = () => new Promise((resolve) => {
|
|
2515
2497
|
execFile("node", ["--version"], {
|
|
@@ -2594,6 +2576,7 @@ async function replaceFolder(source, target) {
|
|
|
2594
2576
|
}
|
|
2595
2577
|
}
|
|
2596
2578
|
const parseMajor = (version) => Number(/^v?(\d+)\./u.exec(version)?.[1] ?? NaN);
|
|
2579
|
+
/** Whether version `installed` is older than `cli`. An unreadable `installed` counts as older. */
|
|
2597
2580
|
const older = (installed, cli) => {
|
|
2598
2581
|
const parts = (version) => version.split(/[.+-]/u).slice(0, 3).map(Number);
|
|
2599
2582
|
const [a, b] = [parts(installed), parts(cli)];
|
|
@@ -2617,7 +2600,7 @@ async function inspectCli(environment, signal) {
|
|
|
2617
2600
|
return {
|
|
2618
2601
|
cli: "older",
|
|
2619
2602
|
latest,
|
|
2620
|
-
message: `A newer Pageship CLI is published (${latest}; this is ${environment.version}).
|
|
2603
|
+
message: `A newer Pageship CLI is published (${latest}; this is ${environment.version}). Run ${commandLine(updateNext.command, updateNext.args)} to update it, then run ${commandLine(installNext.command, installNext.args)}.`
|
|
2621
2604
|
};
|
|
2622
2605
|
}
|
|
2623
2606
|
/** The recommended skills and Node that the CLI could not find. It installs none of them. */
|
|
@@ -2909,7 +2892,7 @@ function viewerList(documentId, viewers) {
|
|
|
2909
2892
|
}
|
|
2910
2893
|
/**
|
|
2911
2894
|
* Lists a document's viewers, or changes them. Every removal is matched and every added username
|
|
2912
|
-
* looked up
|
|
2895
|
+
* looked up first, then one sharing change applies them all or none.
|
|
2913
2896
|
*/
|
|
2914
2897
|
function manageViewers(options) {
|
|
2915
2898
|
const { documentId, add, remove } = options;
|
|
@@ -2927,13 +2910,11 @@ function manageViewers(options) {
|
|
|
2927
2910
|
...add.flatMap((value) => ["--add", value])
|
|
2928
2911
|
]
|
|
2929
2912
|
};
|
|
2913
|
+
if (add.length > sharingLimits.add || remove.length > sharingLimits.remove) return {
|
|
2914
|
+
status: "usage_error",
|
|
2915
|
+
message: `Add up to ${sharingLimits.add} and remove up to ${sharingLimits.remove} viewers at a time. Nothing was changed.`
|
|
2916
|
+
};
|
|
2930
2917
|
const progress = [];
|
|
2931
|
-
const added = [];
|
|
2932
|
-
const removed = [];
|
|
2933
|
-
const changed = () => added.length || removed.length ? {
|
|
2934
|
-
added,
|
|
2935
|
-
removed
|
|
2936
|
-
} : {};
|
|
2937
2918
|
try {
|
|
2938
2919
|
const { viewers } = await getDocumentViewers(origin, documentId, request);
|
|
2939
2920
|
if (!add.length && !remove.length) return {
|
|
@@ -2965,38 +2946,39 @@ function manageViewers(options) {
|
|
|
2965
2946
|
user,
|
|
2966
2947
|
message: `${account(user)} is ${user.type === "organization" ? "an organization" : "not a personal account"}. Only a personal GitHub account can be a viewer. Nothing was changed.`
|
|
2967
2948
|
};
|
|
2949
|
+
if (removals.some(({ githubAccountId }) => githubAccountId === user.githubAccountId)) return {
|
|
2950
|
+
status: "usage_error",
|
|
2951
|
+
message: `${account(user)} is both added and removed. Nothing was changed.`
|
|
2952
|
+
};
|
|
2968
2953
|
progress.push(`Found ${account(user)}.`);
|
|
2969
2954
|
if (!accounts.some(({ githubAccountId }) => githubAccountId === user.githubAccountId)) accounts.push(user);
|
|
2970
2955
|
}
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
added.push(viewer);
|
|
2979
|
-
progress.push(`Added ${account(viewer)}.`);
|
|
2980
|
-
}
|
|
2981
|
-
const current = await getDocumentViewers(origin, documentId, request);
|
|
2956
|
+
const { added, removed, ...shared } = await updateDocumentSharing(origin, documentId, {
|
|
2957
|
+
add: accounts.map(({ githubAccountId, login }) => ({
|
|
2958
|
+
githubAccountId,
|
|
2959
|
+
login
|
|
2960
|
+
})),
|
|
2961
|
+
remove: removals.map(({ githubAccountId }) => githubAccountId)
|
|
2962
|
+
}, request);
|
|
2982
2963
|
return {
|
|
2983
2964
|
status: "viewers_updated",
|
|
2984
2965
|
documentId,
|
|
2985
2966
|
added,
|
|
2986
2967
|
removed,
|
|
2987
2968
|
notViewers,
|
|
2988
|
-
viewers:
|
|
2969
|
+
viewers: shared.viewers,
|
|
2989
2970
|
message: [
|
|
2990
2971
|
...progress,
|
|
2972
|
+
...removed.map((viewer) => `Removed ${account(viewer)}.`),
|
|
2973
|
+
...added.map((viewer) => `Added ${account(viewer)}.`),
|
|
2991
2974
|
...notViewers.map((value) => `${value} is not a viewer of ${documentId}.`),
|
|
2992
|
-
viewerList(documentId,
|
|
2975
|
+
viewerList(documentId, shared.viewers)
|
|
2993
2976
|
].join("\n")
|
|
2994
2977
|
};
|
|
2995
2978
|
} catch (error) {
|
|
2996
2979
|
const prefix = (result) => ({
|
|
2997
2980
|
...result,
|
|
2998
2981
|
documentId,
|
|
2999
|
-
...changed(),
|
|
3000
2982
|
message: [...progress, result.message].join("\n")
|
|
3001
2983
|
});
|
|
3002
2984
|
if (isRefusal(error)) {
|
|
@@ -3013,20 +2995,182 @@ function manageViewers(options) {
|
|
|
3013
2995
|
});
|
|
3014
2996
|
return prefix(refusal(error, login));
|
|
3015
2997
|
}
|
|
3016
|
-
if (!added.length && !removed.length) throw error;
|
|
3017
2998
|
return prefix(options.signal.aborted ? {
|
|
3018
2999
|
status: "interrupted",
|
|
3019
3000
|
message: `Operation interrupted. Run ${commandLine(next.command, next.args)} to finish.`,
|
|
3020
3001
|
next
|
|
3021
3002
|
} : {
|
|
3022
3003
|
status: "request_failed",
|
|
3023
|
-
message: `${error instanceof Error ? error.message : String(error)} Run ${commandLine(next.command, next.args)} to
|
|
3004
|
+
message: `${error instanceof Error ? error.message : String(error)} Run ${commandLine(next.command, next.args)} to retry.`,
|
|
3024
3005
|
next
|
|
3025
3006
|
});
|
|
3026
3007
|
}
|
|
3027
3008
|
});
|
|
3028
3009
|
}
|
|
3029
3010
|
//#endregion
|
|
3011
|
+
//#region src/update.ts
|
|
3012
|
+
/**
|
|
3013
|
+
* The command that updates a global install with each manager. Keep in sync with the setup
|
|
3014
|
+
* guide. The package names an exact version where one is known: pnpm resolves `latest` to the
|
|
3015
|
+
* newest version older than its minimum release age, so a fresh release would not install.
|
|
3016
|
+
*/
|
|
3017
|
+
const updateCommand$1 = (manager, spec) => ({
|
|
3018
|
+
npm: [
|
|
3019
|
+
"npm",
|
|
3020
|
+
"i",
|
|
3021
|
+
"-g",
|
|
3022
|
+
spec
|
|
3023
|
+
],
|
|
3024
|
+
pnpm: [
|
|
3025
|
+
"pnpm",
|
|
3026
|
+
"add",
|
|
3027
|
+
"-g",
|
|
3028
|
+
spec
|
|
3029
|
+
],
|
|
3030
|
+
bun: [
|
|
3031
|
+
"bun",
|
|
3032
|
+
"add",
|
|
3033
|
+
"-g",
|
|
3034
|
+
spec
|
|
3035
|
+
],
|
|
3036
|
+
yarn: [
|
|
3037
|
+
"yarn",
|
|
3038
|
+
"global",
|
|
3039
|
+
"add",
|
|
3040
|
+
spec
|
|
3041
|
+
],
|
|
3042
|
+
vp: [
|
|
3043
|
+
"vp",
|
|
3044
|
+
"install",
|
|
3045
|
+
"-g",
|
|
3046
|
+
spec
|
|
3047
|
+
]
|
|
3048
|
+
})[manager];
|
|
3049
|
+
const npmRoot = (signal) => new Promise((resolve) => {
|
|
3050
|
+
exec("npm root -g", {
|
|
3051
|
+
timeout: 1e4,
|
|
3052
|
+
windowsHide: true,
|
|
3053
|
+
signal
|
|
3054
|
+
}, (error, stdout) => resolve(error ? void 0 : stdout.trim() || void 0));
|
|
3055
|
+
});
|
|
3056
|
+
/**
|
|
3057
|
+
* Run a command with the terminal attached, or, for `--json`, with its output collected so
|
|
3058
|
+
* standard output stays one JSON value.
|
|
3059
|
+
*/
|
|
3060
|
+
const runCommand = (json) => (argv, signal) => new Promise((resolve, reject) => {
|
|
3061
|
+
const [command, ...args] = argv;
|
|
3062
|
+
if (!json) console.log(`Running ${argv.join(" ")}`);
|
|
3063
|
+
const stdio = json ? [
|
|
3064
|
+
"ignore",
|
|
3065
|
+
"pipe",
|
|
3066
|
+
"pipe"
|
|
3067
|
+
] : "inherit";
|
|
3068
|
+
const child = process.platform === "win32" ? spawn(argv.join(" "), {
|
|
3069
|
+
stdio,
|
|
3070
|
+
shell: true,
|
|
3071
|
+
windowsHide: true
|
|
3072
|
+
}) : spawn(command, args, { stdio });
|
|
3073
|
+
const stop = () => child.kill("SIGTERM");
|
|
3074
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
3075
|
+
const settle = () => signal.removeEventListener("abort", stop);
|
|
3076
|
+
let output = "";
|
|
3077
|
+
const collect = (chunk) => {
|
|
3078
|
+
output = (output + chunk.toString()).slice(-4e3);
|
|
3079
|
+
};
|
|
3080
|
+
child.stdout?.on("data", collect);
|
|
3081
|
+
child.stderr?.on("data", collect);
|
|
3082
|
+
child.once("error", (error) => {
|
|
3083
|
+
settle();
|
|
3084
|
+
reject(error);
|
|
3085
|
+
});
|
|
3086
|
+
child.once("close", (exitCode) => {
|
|
3087
|
+
settle();
|
|
3088
|
+
resolve({
|
|
3089
|
+
exitCode,
|
|
3090
|
+
output
|
|
3091
|
+
});
|
|
3092
|
+
});
|
|
3093
|
+
});
|
|
3094
|
+
/** A path with forward slashes and a trailing slash, compared without case on Windows. */
|
|
3095
|
+
function comparable(path, platform) {
|
|
3096
|
+
const slashed = `${path.replaceAll("\\", "/").replace(/\/+$/u, "")}/`;
|
|
3097
|
+
return platform === "win32" ? slashed.toLowerCase() : slashed;
|
|
3098
|
+
}
|
|
3099
|
+
/**
|
|
3100
|
+
* Which manager installed this CLI globally, from where its package is. Undefined for anything
|
|
3101
|
+
* else, such as a project dependency or an npx cache, which `update` must not replace.
|
|
3102
|
+
*/
|
|
3103
|
+
async function detectManager(environment, signal) {
|
|
3104
|
+
const { platform, env } = environment;
|
|
3105
|
+
const root = comparable(environment.packageRoot, platform);
|
|
3106
|
+
const installed = (folders, layout) => folders.some((folder) => {
|
|
3107
|
+
if (!folder) return false;
|
|
3108
|
+
const base = comparable(folder, platform);
|
|
3109
|
+
const index = root.lastIndexOf(base);
|
|
3110
|
+
return index !== -1 && layout.test(root.slice(index + base.length));
|
|
3111
|
+
});
|
|
3112
|
+
if (installed(["/vite-plus/packages/"], /^pageship\/[^/]+\/(?:lib\/)?node_modules\/pageship\/$/u)) return "vp";
|
|
3113
|
+
if (installed(["/pnpm/global/", env.PNPM_HOME && join(env.PNPM_HOME, "global")], /^[^/]+\/(?:[^/]+\/)?node_modules\/\.pnpm\/pageship@[^/]+\/node_modules\/pageship\/$/u)) return "pnpm";
|
|
3114
|
+
if (installed(["/.bun/", env.BUN_INSTALL], /^install\/global\/node_modules\/pageship\/$/u) || installed([env.BUN_INSTALL_GLOBAL_DIR], /^node_modules\/pageship\/$/u)) return "bun";
|
|
3115
|
+
if (installed(["/yarn/global/", "/yarn/data/global/"], /^node_modules\/pageship\/$/u)) return "yarn";
|
|
3116
|
+
const npm = await environment.npmRoot(signal);
|
|
3117
|
+
const parent = root.slice(0, root.lastIndexOf("/", root.length - 2) + 1);
|
|
3118
|
+
if (npm !== void 0 && parent === comparable(npm, platform)) return "npm";
|
|
3119
|
+
}
|
|
3120
|
+
/**
|
|
3121
|
+
* Update this CLI to the version npm publishes as latest, with the package manager that
|
|
3122
|
+
* installed it. It changes nothing when this CLI is already the latest.
|
|
3123
|
+
*/
|
|
3124
|
+
async function update(environment, signal) {
|
|
3125
|
+
const { version } = environment;
|
|
3126
|
+
const latest = await environment.publishedVersion(signal);
|
|
3127
|
+
if (latest !== void 0 && !older(version, latest)) return {
|
|
3128
|
+
status: "cli_current",
|
|
3129
|
+
message: `Pageship ${version} is the latest version.`,
|
|
3130
|
+
version,
|
|
3131
|
+
latest
|
|
3132
|
+
};
|
|
3133
|
+
const manager = await detectManager(environment, signal);
|
|
3134
|
+
signal.throwIfAborted();
|
|
3135
|
+
if (manager === void 0) return {
|
|
3136
|
+
status: "install_unknown",
|
|
3137
|
+
message: `This Pageship CLI, in ${environment.packageRoot}, was not installed globally by npm, pnpm, bun, Yarn or Vite+, so update cannot tell how to replace it. Update it the way you installed it.`,
|
|
3138
|
+
version,
|
|
3139
|
+
...latest === void 0 ? {} : { latest },
|
|
3140
|
+
path: environment.packageRoot
|
|
3141
|
+
};
|
|
3142
|
+
const argv = updateCommand$1(manager, `pageship@${latest ?? "latest"}`);
|
|
3143
|
+
const run = argv.join(" ");
|
|
3144
|
+
const ran = await environment.run(argv, signal).catch((error) => {
|
|
3145
|
+
if (signal.aborted) throw error;
|
|
3146
|
+
return {
|
|
3147
|
+
exitCode: null,
|
|
3148
|
+
output: error instanceof Error ? error.message : String(error)
|
|
3149
|
+
};
|
|
3150
|
+
});
|
|
3151
|
+
signal.throwIfAborted();
|
|
3152
|
+
if (ran.exitCode !== 0) return {
|
|
3153
|
+
status: "update_failed",
|
|
3154
|
+
message: [ran.exitCode === null ? `Could not run ${run}.` : `${run} failed with exit code ${ran.exitCode}.`, ran.output.trim()].filter(Boolean).join("\n"),
|
|
3155
|
+
version,
|
|
3156
|
+
...latest === void 0 ? {} : { latest },
|
|
3157
|
+
manager,
|
|
3158
|
+
run,
|
|
3159
|
+
exitCode: ran.exitCode,
|
|
3160
|
+
output: ran.output
|
|
3161
|
+
};
|
|
3162
|
+
const skills = await stat(join(environment.home, ".agents", "skills", "pageship")).then(() => true, () => false);
|
|
3163
|
+
return {
|
|
3164
|
+
status: "cli_updated",
|
|
3165
|
+
message: [latest === void 0 ? `Updated Pageship from ${version} with ${run}.` : `Updated Pageship from ${version} to ${latest} with ${run}.`, ...skills ? [`Run ${commandLine(installNext.command, installNext.args)} to update the Pageship skills to match.`] : []].join("\n"),
|
|
3166
|
+
version,
|
|
3167
|
+
...latest === void 0 ? {} : { latest },
|
|
3168
|
+
manager,
|
|
3169
|
+
run,
|
|
3170
|
+
...skills ? { next: installNext } : {}
|
|
3171
|
+
};
|
|
3172
|
+
}
|
|
3173
|
+
//#endregion
|
|
3030
3174
|
//#region src/cli.ts
|
|
3031
3175
|
const args = process.argv.slice(2);
|
|
3032
3176
|
const separator = args.indexOf("--");
|
|
@@ -3093,6 +3237,13 @@ const skills = Command.make("skills").pipe(Command.withDescription("Manage the P
|
|
|
3093
3237
|
force,
|
|
3094
3238
|
signal
|
|
3095
3239
|
}))).pipe(Command.withDescription("Install the Pageship skills in ~/.agents/skills, and link them in ~/.claude/skills when ~/.claude exists."))]));
|
|
3240
|
+
const updateCommand = Command.make("update", {}, () => authCommand("update", (signal) => update({
|
|
3241
|
+
...skillsEnvironment,
|
|
3242
|
+
packageRoot: dirname(dirname(fileURLToPath(import.meta.url))),
|
|
3243
|
+
env: process.env,
|
|
3244
|
+
npmRoot,
|
|
3245
|
+
run: runCommand(json)
|
|
3246
|
+
}, signal))).pipe(Command.withDescription("Update this CLI to the latest version with the package manager that installed it: npm, pnpm, bun, Yarn or Vite+."));
|
|
3096
3247
|
const login = Command.make("login", {
|
|
3097
3248
|
complete: Flag.boolean("complete").pipe(Flag.withDefault(false), Flag.withDescription("Check a pending authorization once, without waiting.")),
|
|
3098
3249
|
restart: Flag.boolean("restart").pipe(Flag.withDefault(false), Flag.withDescription("Start a new authorization code.")),
|
|
@@ -3253,7 +3404,7 @@ function authCommand(name, operation) {
|
|
|
3253
3404
|
settle(name, result);
|
|
3254
3405
|
if (json) return;
|
|
3255
3406
|
if (thrown) {
|
|
3256
|
-
console.error(`${name === "status" ? "Could not check status" : name === "skills" ? "Could not install the Pageship skills" : "Pageship request failed"}: ${result.message}`);
|
|
3407
|
+
console.error(`${name === "status" ? "Could not check status" : name === "skills" ? "Could not install the Pageship skills" : name === "update" ? "Could not update Pageship" : "Pageship request failed"}: ${result.message}`);
|
|
3257
3408
|
return;
|
|
3258
3409
|
}
|
|
3259
3410
|
console.log(result.message);
|
|
@@ -3264,7 +3415,7 @@ function authCommand(name, operation) {
|
|
|
3264
3415
|
}
|
|
3265
3416
|
});
|
|
3266
3417
|
}
|
|
3267
|
-
const command = Command.make("pageship").pipe(Command.withDescription("Pageship publishes private HTML documents on the hosted Pageship service.\n\nEarly development: check whether this installation is ready with the status command. Authorize this installation with login, then publish one HTML file with publish. Manage published documents with list, history, download, visibility, viewers and restore. Install the Pageship skills for your agents with skills install."), Command.withSubcommands([
|
|
3418
|
+
const command = Command.make("pageship").pipe(Command.withDescription("Pageship publishes private HTML documents on the hosted Pageship service.\n\nEarly development: check whether this installation is ready with the status command. Authorize this installation with login, then publish one HTML file with publish. Manage published documents with list, history, download, visibility, viewers and restore. Install the Pageship skills for your agents with skills install, and update the CLI with update."), Command.withSubcommands([
|
|
3268
3419
|
status,
|
|
3269
3420
|
login,
|
|
3270
3421
|
whoami,
|
|
@@ -3275,7 +3426,8 @@ const command = Command.make("pageship").pipe(Command.withDescription("Pageship
|
|
|
3275
3426
|
visibility,
|
|
3276
3427
|
viewers,
|
|
3277
3428
|
restore,
|
|
3278
|
-
skills
|
|
3429
|
+
skills,
|
|
3430
|
+
updateCommand
|
|
3279
3431
|
]), Command.withGlobalFlags([jsonFlag]));
|
|
3280
3432
|
const effectiveArgs = args.every((arg, index) => arg === "--json" || arg.startsWith("--json=") && booleanValue(arg.slice(7)) !== void 0 || index > 0 && args[index - 1] === "--json" && booleanValue(arg) !== void 0) ? [...args, "--help"] : args;
|
|
3281
3433
|
const program = Command.runWith(command, {
|
|
@@ -3,7 +3,7 @@ name: pageship
|
|
|
3
3
|
description: Publish an HTML file to Pageship and manage what is published. Use when the user asks to publish, share or get a link to a document, update its published copy, change its visibility or viewers, list, inspect history, download or restore published documents, or sign in to Pageship. To write, edit, rename or move a document, load pageship-docs instead.
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Pageship
|
|
@@ -33,6 +33,7 @@ With `--json`, the CLI prints one JSON object on one line. Parse it before you d
|
|
|
33
33
|
- `next` is one follow-up command. `resolutions` holds named alternatives for a decision, each a follow-up command or a list of them.
|
|
34
34
|
- Other fields depend on the status, such as `document`, `candidates`, `choices`, `user` or `idempotencyKey`.
|
|
35
35
|
- `skills install` returns `skills_installed` or `skills_modified`, as described in [Install the Pageship skills](#install-the-pageship-skills).
|
|
36
|
+
- `update` returns `cli_updated`, `cli_current`, `install_unknown` or `update_failed`, as described in [Update the CLI](#update-the-cli).
|
|
36
37
|
|
|
37
38
|
A follow-up has a `command` and an `args` array. Run it as `pageship --json <command> <args...>` with `args` unchanged. They already carry the server, target document, expected revision and retry key, so never rebuild them from memory.
|
|
38
39
|
|
|
@@ -50,7 +51,17 @@ pageship --json status
|
|
|
50
51
|
|
|
51
52
|
Status only reads; it never signs in, claims an address or uploads. On `admitted`, sign-in and the workspace address are set, unless `next` is a `login`: that comes from an older server that does not report the address, and running it confirms the address. A `next` of `skills install` on `admitted` is about the skills, below. On `signed_out` or `address_required`, sign in as described below. On `uninvited`, report the `message`: the user must ask the server owner for an invitation, or sign in with another account using `login --restart`. On `unreachable`, `client_too_old`, `server_too_old`, `unsupported` or `configuration_unreadable`, report the `message`; signing in does not fix these. A ready status does not prove that a publish will succeed.
|
|
52
53
|
|
|
53
|
-
Status also reports the Pageship skills in `skills`: `missing`, `current` or `older` than the CLI. They never block publishing, and a status that is otherwise ready still succeeds. When `skills` is `missing` or `older`, tell the user, and install them as below only if they agree. Never run a `skills install` from `next` without asking. When `cli` is `older`, a newer CLI is published: tell the user, and offer to update it
|
|
54
|
+
Status also reports the Pageship skills in `skills`: `missing`, `current` or `older` than the CLI. They never block publishing, and a status that is otherwise ready still succeeds. When `skills` is `missing` or `older`, tell the user, and install them as below only if they agree. Never run a `skills install` from `next` without asking. When `cli` is `older`, a newer CLI is published: tell the user, and offer to update it, as below, before installing the skills.
|
|
55
|
+
|
|
56
|
+
## Update the CLI
|
|
57
|
+
|
|
58
|
+
With the user's agreement, update the CLI with the package manager that installed it:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
pageship --json update
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
On `cli_updated`, the new version is installed. Its `next` is a `skills install`, present when the Pageship skills are installed, since they still match the old version: install them as below if the user agrees. On `cli_current`, the CLI is already the latest. On `install_unknown`, no supported package manager installed it globally, so nothing ran; tell the user to update it the way they installed it. On `update_failed`, report the `message`, which carries the package manager's error.
|
|
54
65
|
|
|
55
66
|
## Install the Pageship skills
|
|
56
67
|
|
|
@@ -12,7 +12,7 @@ Set `PAGESHIP_DOCUMENT` to the document's `id`, then add each named username wit
|
|
|
12
12
|
pageship --json viewers "$PAGESHIP_DOCUMENT" --add octocat --add hubot
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
The CLI looks each username up on GitHub before it changes anything. `added` holds each account it added, with `login`, `name` and `githubAccountId
|
|
15
|
+
The CLI looks each username up on GitHub before it changes anything. On `viewers_updated`, `added` holds each account it added, with `login`, `name` and `githubAccountId`. Show the user every account in `added` by `login` and `name`, and ask them to confirm each is the person they meant. A username can belong to someone else. If one is wrong, remove it as below. Then give the user the document's `url` to send: Pageship sends no invitations.
|
|
16
16
|
|
|
17
17
|
## List and remove viewers
|
|
18
18
|
|
|
@@ -40,4 +40,4 @@ pageship --json viewers "$PAGESHIP_DOCUMENT" --remove octocat
|
|
|
40
40
|
- `github_sign_in_required`: GitHub refused the sign-in Pageship uses to look up users. Ask the user to sign in to the Pageship dashboard again with GitHub, then run the returned `next`. A CLI `login` doesn't fix this.
|
|
41
41
|
- `github_rate_limited` or `github_unavailable`: wait a minute, then run the returned `next`.
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
The command adds and removes everyone together or no one. On any failure, nothing changed. Its `next` repeats the whole command. It takes up to 20 `--add` and 50 `--remove` values; split a longer list across several commands.
|
|
@@ -3,7 +3,7 @@ name: pageship-chart
|
|
|
3
3
|
description: "Later step of pageship-docs: for a request to write or edit a document, load pageship-docs first; load this skill first only when the user names it. Pattern for charts in a Pageship HTML document, loaded by a pageship- kind skill before it draws a chart."
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Chart
|
|
@@ -3,7 +3,7 @@ name: pageship-code-block
|
|
|
3
3
|
description: "Later step of pageship-docs: for a request to write or edit a document, load pageship-docs first; load this skill first only when the user names it. Pattern for code in a Pageship HTML document, such as source code, commands, configuration or logs, loaded by a pageship- kind skill before the first code block."
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Code block
|
|
@@ -3,7 +3,7 @@ name: pageship-decision-record
|
|
|
3
3
|
description: HTML decision records, as the second step of pageship-docs. For any request to record, write, regenerate, edit or move a decision, load pageship-docs first; load this skill first only when the user names it.
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Decision record
|
|
@@ -3,7 +3,7 @@ name: pageship-diagram
|
|
|
3
3
|
description: "Later step of pageship-docs: for a request to write or edit a document, load pageship-docs first; load this skill first only when the user names it. Pattern for diagrams in a Pageship HTML document, such as a process, a timeline, a system map or states, loaded by a pageship- kind skill before it draws a diagram."
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Diagram
|
|
@@ -3,7 +3,7 @@ name: pageship-docs
|
|
|
3
3
|
description: First step for any document people read, such as a report, plan, spec, explainer, review, decision record or slide deck, in HTML or Markdown. Load it before any other pageship- skill. Use when the user asks for one of these documents, asks to regenerate, redesign, edit, rename, move or copy an HTML source file, or asks to record whether they want HTML or Markdown.
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Pageship documents
|
|
@@ -3,7 +3,7 @@ name: pageship-explainer
|
|
|
3
3
|
description: HTML explainers, as the second step of pageship-docs. For any request to explain how something works, or to write, regenerate, edit or move an explainer, load pageship-docs first; load this skill first only when the user names it.
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Explainer
|
|
@@ -3,7 +3,7 @@ name: pageship-interaction
|
|
|
3
3
|
description: "Later step of pageship-docs: for a request to write or edit a document, load pageship-docs first; load this skill first only when the user names it. Pattern for controls in a Pageship HTML document, such as stepping through stages, tracing a path, tabs, filters, revealing detail and pointer states on charts and diagrams, loaded by a pageship- kind skill before it adds any control."
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Interaction
|
|
@@ -3,7 +3,7 @@ name: pageship-key-figures
|
|
|
3
3
|
description: "Later step of pageship-docs: for a request to write or edit a document, load pageship-docs first; load this skill first only when the user names it. Pattern for the few numbers and callouts a Pageship HTML document opens with, loaded by a pageship- kind skill before it writes key figures."
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Key figures
|
|
@@ -3,7 +3,7 @@ name: pageship-media
|
|
|
3
3
|
description: "Later step of pageship-docs: for a request to write or edit a document, load pageship-docs first; load this skill first only when the user names it. Pattern for images, video and audio in a Pageship HTML document, loaded by a pageship- kind skill before it shows media."
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Media
|
|
@@ -3,7 +3,7 @@ name: pageship-motion
|
|
|
3
3
|
description: "Later step of pageship-docs: for a request to write or edit a document, load pageship-docs first; load this skill first only when the user names it. Pattern for animation and transitions in a Pageship HTML document, such as a chart that grows into view, a sequence that plays through a diagram, or a marker moving along a path, loaded by a pageship- kind skill before it draws a chart, a graphic or a sequence, or before anything else on the page moves."
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Motion
|
|
@@ -3,7 +3,7 @@ name: pageship-plan
|
|
|
3
3
|
description: HTML plans, as the second step of pageship-docs. For any request to write, regenerate, edit or move a plan, load pageship-docs first; load this skill first only when the user names it.
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Plan
|
|
@@ -3,7 +3,7 @@ name: pageship-report
|
|
|
3
3
|
description: HTML reports, as the second step of pageship-docs. For any request to write, regenerate, edit or move a report, load pageship-docs first; load this skill first only when the user names it.
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Report
|
|
@@ -3,7 +3,7 @@ name: pageship-review-report
|
|
|
3
3
|
description: HTML review reports, as the second step of pageship-docs. For any request to review a change or a plan and write up the findings, or to write, regenerate, edit or move a review report, load pageship-docs first; load this skill first only when the user names it.
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Review report
|
|
@@ -3,7 +3,7 @@ name: pageship-slide-deck
|
|
|
3
3
|
description: HTML slide decks, as the second step of pageship-docs. For any request to make slides or a presentation, or to regenerate, edit or move a deck, load pageship-docs first; load this skill first only when the user names it.
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Slide deck
|
|
@@ -3,7 +3,7 @@ name: pageship-spec
|
|
|
3
3
|
description: HTML specs, as the second step of pageship-docs. For any request to write, regenerate, edit or move a spec, load pageship-docs first; load this skill first only when the user names it.
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Spec
|
|
@@ -3,7 +3,7 @@ name: pageship-table
|
|
|
3
3
|
description: "Later step of pageship-docs: for a request to write or edit a document, load pageship-docs first; load this skill first only when the user names it. Pattern for tables in a Pageship HTML document, loaded by a pageship- kind skill before it writes a table."
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Table
|