@wirecat/cli-base 0.42.0 → 0.43.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/dist/release/markdown.d.ts +6 -1
- package/dist/release/markdown.d.ts.map +1 -1
- package/dist/release/markdown.js +20 -3
- package/dist/release/markdown.js.map +1 -1
- package/dist/standards/audit.js +1 -1
- package/dist/standards/audit.js.map +1 -1
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +1 -0
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/network.d.ts +15 -0
- package/dist/testing/network.d.ts.map +1 -0
- package/dist/testing/network.js +114 -0
- package/dist/testing/network.js.map +1 -0
- package/dist/testing/sandbox.d.ts +20 -0
- package/dist/testing/sandbox.d.ts.map +1 -0
- package/dist/testing/sandbox.js +76 -0
- package/dist/testing/sandbox.js.map +1 -0
- package/dist/testing/setup.d.ts +2 -0
- package/dist/testing/setup.d.ts.map +1 -0
- package/dist/testing/setup.js +13 -0
- package/dist/testing/setup.js.map +1 -0
- package/docs/standards/README.md +2 -2
- package/docs/standards/accounts.md +2 -1
- package/docs/standards/commands.md +43 -0
- package/docs/standards/docs.md +7 -2
- package/docs/standards/layout.md +3 -2
- package/docs/standards/lifecycle.md +45 -2
- package/docs/standards/store.md +5 -4
- package/docs/standards/testing.md +28 -18
- package/package.json +10 -2
|
@@ -7,13 +7,18 @@ export type ChangelogRules = {
|
|
|
7
7
|
/** The top section's title until it is dated, `Unreleased` or `Не выпущено`. */
|
|
8
8
|
unreleased: string;
|
|
9
9
|
ids: readonly string[];
|
|
10
|
+
/**
|
|
11
|
+
* Sections at or below this version keep the `###` headings they were released with, repeats included: a
|
|
12
|
+
* released section is never edited, so a check on it could only fail.
|
|
13
|
+
*/
|
|
14
|
+
legacyHeadingsThrough?: string;
|
|
10
15
|
};
|
|
11
16
|
/**
|
|
12
17
|
* `release`: the top section must be `version`, and nothing may be left unreleased — a release
|
|
13
18
|
* workflow builds its notes by matching `## <version> `, so a heading slightly off publishes empty
|
|
14
19
|
* notes without an error.
|
|
15
20
|
*/
|
|
16
|
-
export declare const changelogProblems: (text: string, { version, release, headings, unreleased, ids }: ChangelogRules & {
|
|
21
|
+
export declare const changelogProblems: (text: string, { version, release, headings, unreleased, ids, legacyHeadingsThrough, }: ChangelogRules & {
|
|
17
22
|
version?: string;
|
|
18
23
|
release: boolean;
|
|
19
24
|
}) => string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/release/markdown.ts"],"names":[],"mappings":"AAGA,yFAAyF;AACzF,eAAO,MAAM,WAAW,YAAI,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAU,CAAA;AAEvH,eAAO,MAAM,SAAS,aAAc,SAAS,MAAM,EAAE,WAA4D,CAAA;AAIjH,MAAM,MAAM,cAAc,GAAG;IAC3B,kDAAkD;IAClD,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,EAAE,SAAS,MAAM,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/release/markdown.ts"],"names":[],"mappings":"AAGA,yFAAyF;AACzF,eAAO,MAAM,WAAW,YAAI,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAU,CAAA;AAEvH,eAAO,MAAM,SAAS,aAAc,SAAS,MAAM,EAAE,WAA4D,CAAA;AAIjH,MAAM,MAAM,cAAc,GAAG;IAC3B,kDAAkD;IAClD,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,EAAE,SAAS,MAAM,EAAE,CAAA;IACtB;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAC/B,CAAA;AAcD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,SACtB,MAAM,2EAQT,cAAc,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,aA8C3D,CAAA;AAED,0GAA0G;AAC1G,eAAO,MAAM,IAAI,YAAa,MAAM,WAMb,CAAA;AAEvB,eAAO,MAAM,WAAW,SAAU,MAAM,WAGqB,CAAA;AAsB7D,sFAAsF;AACtF,eAAO,MAAM,aAAa,cAAe,MAAM,SAAQ,WAAW,CAAC,MAAM,CAAC,KAAe,MAAM,EAWvF,CAAA;AAER,MAAM,MAAM,SAAS,GAAG;IACtB,oDAAoD;IACpD,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,GAAG,EAAE,SAAS,MAAM,EAAE,CAAA;IACtB,sGAAsG;IACtG,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;IACpC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAA;CAC5D,CAAA;AAED,eAAO,MAAM,YAAY,SACjB,MAAM,kDACsF,SAAS,aA8C5G,CAAA"}
|
package/dist/release/markdown.js
CHANGED
|
@@ -4,22 +4,38 @@ import { dirname, join, relative, resolve } from "node:path";
|
|
|
4
4
|
export const JOURNAL_IDS = ["NEED", "FIND", "BUG", "SEC", "PERF", "UX", "IDEA", "RISK", "DEBT", "ASK", "TASK"];
|
|
5
5
|
export const idPattern = (prefixes) => new RegExp(`\\b(?:${prefixes.join("|")})-\\d+\\b`, "g");
|
|
6
6
|
const VERSION_HEADING = /^## (\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?) — (\d{2})\.(\d{2})\.(\d{4})$/;
|
|
7
|
+
const versionParts = (version) => {
|
|
8
|
+
const [core = "", pre] = version.split("-", 2);
|
|
9
|
+
return [...core.split(".").map(Number), pre === undefined ? 1 : 0];
|
|
10
|
+
};
|
|
11
|
+
const atOrBelow = (version, through) => {
|
|
12
|
+
const a = versionParts(version);
|
|
13
|
+
const b = versionParts(through);
|
|
14
|
+
for (let i = 0; i < 4; i++)
|
|
15
|
+
if ((a[i] ?? 0) !== (b[i] ?? 0))
|
|
16
|
+
return (a[i] ?? 0) < (b[i] ?? 0);
|
|
17
|
+
return true;
|
|
18
|
+
};
|
|
7
19
|
/**
|
|
8
20
|
* `release`: the top section must be `version`, and nothing may be left unreleased — a release
|
|
9
21
|
* workflow builds its notes by matching `## <version> `, so a heading slightly off publishes empty
|
|
10
22
|
* notes without an error.
|
|
11
23
|
*/
|
|
12
|
-
export const changelogProblems = (text, { version, release, headings, unreleased, ids }) => {
|
|
24
|
+
export const changelogProblems = (text, { version, release, headings, unreleased, ids, legacyHeadingsThrough, }) => {
|
|
13
25
|
const problems = [];
|
|
14
26
|
const id = idPattern(ids);
|
|
15
27
|
let section;
|
|
16
28
|
let subheadings = new Set();
|
|
17
29
|
let first = true;
|
|
30
|
+
let legacy = false;
|
|
31
|
+
if (legacyHeadingsThrough !== undefined && !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(legacyHeadingsThrough))
|
|
32
|
+
problems.push(`legacyHeadingsThrough: "${legacyHeadingsThrough}" is not a version`);
|
|
18
33
|
text.split("\n").forEach((line, index) => {
|
|
19
34
|
const where = `CHANGELOG.md:${index + 1}`;
|
|
20
35
|
if (line.startsWith("## ")) {
|
|
21
36
|
section = line.slice(3);
|
|
22
37
|
subheadings = new Set();
|
|
38
|
+
legacy = false;
|
|
23
39
|
if (section === unreleased) {
|
|
24
40
|
if (release)
|
|
25
41
|
problems.push(`${where}: "${unreleased}" is left — date it as ${version} before releasing`);
|
|
@@ -31,7 +47,8 @@ export const changelogProblems = (text, { version, release, headings, unreleased
|
|
|
31
47
|
if (!found)
|
|
32
48
|
problems.push(`${where}: "${line}" is not "## <version> — DD.MM.YYYY"`);
|
|
33
49
|
else {
|
|
34
|
-
const [, heading, day, month] = found;
|
|
50
|
+
const [, heading = "", day, month] = found;
|
|
51
|
+
legacy = legacyHeadingsThrough !== undefined && atOrBelow(heading, legacyHeadingsThrough);
|
|
35
52
|
if (Number(day) < 1 || Number(day) > 31 || Number(month) < 1 || Number(month) > 12)
|
|
36
53
|
problems.push(`${where}: "${line}" has no such date`);
|
|
37
54
|
if (release && first && heading !== version)
|
|
@@ -41,7 +58,7 @@ export const changelogProblems = (text, { version, release, headings, unreleased
|
|
|
41
58
|
first = false;
|
|
42
59
|
return;
|
|
43
60
|
}
|
|
44
|
-
if (line.startsWith("### ")) {
|
|
61
|
+
if (line.startsWith("### ") && !legacy) {
|
|
45
62
|
const heading = line.slice(4);
|
|
46
63
|
if (!headings.includes(heading))
|
|
47
64
|
problems.push(`${where}: "${heading}" is not one of: ${headings.join(", ")}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/release/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACzE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAE5D,yFAAyF;AACzF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAU,CAAA;AAEvH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,QAA2B,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,SAAS,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;AAEjH,MAAM,eAAe,GAAG,sEAAsE,CAAA;
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/release/markdown.ts"],"names":[],"mappings":"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"}
|
package/dist/standards/audit.js
CHANGED
|
@@ -54,7 +54,7 @@ export const PARITY_GROUPS = defineParityGroups([
|
|
|
54
54
|
{ name: "messengers", members: ["tg", "max"], covers: "tree", differences: [] },
|
|
55
55
|
{
|
|
56
56
|
name: "all",
|
|
57
|
-
members: ["tg", "max", "memo", "drive", "zm"],
|
|
57
|
+
members: ["tg", "max", "memo", "drive", "zm", "wa"],
|
|
58
58
|
covers: ["commands", "doctor", "skill", "mcp", "upgrade", "search", "notes", "meetings"],
|
|
59
59
|
differences: [],
|
|
60
60
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/standards/audit.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/standards/audit.ts"],"names":[],"mappings":"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"}
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { brokenKeyring, memoryKeyring } from "../keyring.js";
|
|
6
6
|
export { captureStreams } from "../streams.js";
|
|
7
|
+
export { allowNetwork } from "./network.js";
|
|
7
8
|
import { type LogEvent } from "../standards/log.js";
|
|
8
9
|
/** Throws, naming each, when a written log line is not a registered event with its keys. */
|
|
9
10
|
export declare const expectRegisteredEvents: (lines: readonly string[], events: readonly LogEvent[]) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,OAAO,EAAE,KAAK,QAAQ,EAAoB,MAAM,qBAAqB,CAAA;AAErE,4FAA4F;AAC5F,eAAO,MAAM,sBAAsB,UAAW,SAAS,MAAM,EAAE,UAAU,SAAS,QAAQ,EAAE,KAAG,IAG9F,CAAA;AAED,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEtE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,cAAc,CAAA;IACrB,GAAG,EAAE,SAAS,CAAA;IACd,KAAK,EAAE,SAAS,CAAA;IAChB,gGAAgG;IAChG,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACxC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,wBAAkB,SAiBvC,CAAA"}
|
package/dist/testing/index.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { brokenKeyring, memoryKeyring } from "../keyring.js";
|
|
6
6
|
export { captureStreams } from "../streams.js";
|
|
7
|
+
export { allowNetwork } from "./network.js";
|
|
7
8
|
import { logEventProblems } from "../standards/log.js";
|
|
8
9
|
/** Throws, naming each, when a written log line is not a registered event with its keys. */
|
|
9
10
|
export const expectRegisteredEvents = (lines, events) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,OAAO,EAAiB,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAErE,4FAA4F;AAC5F,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,KAAwB,EAAE,MAA2B,EAAQ,EAAE;IACpG,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,CAAA;IACpF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AAC9F,CAAC,CAAA;AAaD;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,OAAO,GAAG,CAAC,EAAa,EAAE;IAClD,IAAI,OAAO,GAAG,OAAO,CAAA;IACrB,MAAM,KAAK,GAAsC,EAAE,CAAA;IAEnD,OAAO;QACL,KAAK;QACL,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO;QACpB,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACtC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YAClC,IAAI,MAAM,EAAE,OAAO;gBAAE,MAAM,IAAI,YAAY,CAAC,4BAA4B,EAAE,YAAY,CAAC,CAAA;YACvF,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;YAC1D,OAAO,IAAI,EAAE,CAAA;QACf,CAAC;QACD,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE;YACd,OAAO,IAAI,EAAE,CAAA;QACf,CAAC;KACF,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const networkRefused: (host: string) => Error;
|
|
2
|
+
/**
|
|
3
|
+
* Refuses every outbound connection except to this machine, before any name is looked up.
|
|
4
|
+
* `Socket#connect` is what `net`, `tls`, `http(s)` and Node's own `fetch` all end in; `http(s)`,
|
|
5
|
+
* `fetch` and `WebSocket` are checked first as well, because through them a refused socket surfaces
|
|
6
|
+
* only as "fetch failed", an error event or an uncaught exception, and Bun's `fetch` skips `net`.
|
|
7
|
+
* Installed once per worker and never removed: a worker that runs tests never needs the network.
|
|
8
|
+
*/
|
|
9
|
+
export declare const installNetworkGuard: () => void;
|
|
10
|
+
/**
|
|
11
|
+
* Lets the network through until the returned function is called:
|
|
12
|
+
* `onTestFinished(allowNetwork())`. For the rare test whose subject is the network itself.
|
|
13
|
+
*/
|
|
14
|
+
export declare const allowNetwork: () => (() => void);
|
|
15
|
+
//# sourceMappingURL=network.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/testing/network.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,cAAc,SAAU,MAAM,KAAG,KAI3C,CAAA;AA2DH;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,QAAO,IAgCtC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,QAAO,CAAC,MAAM,IAAI,CAQ1C,CAAA"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import http from "node:http";
|
|
2
|
+
import https from "node:https";
|
|
3
|
+
import { syncBuiltinESMExports } from "node:module";
|
|
4
|
+
import net from "node:net";
|
|
5
|
+
const LOCAL = new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);
|
|
6
|
+
const STATE = Symbol.for("@wirecat/cli-base/testing/network");
|
|
7
|
+
const state = () => {
|
|
8
|
+
const holder = globalThis;
|
|
9
|
+
holder[STATE] ??= { installed: false, allowed: 0 };
|
|
10
|
+
return holder[STATE];
|
|
11
|
+
};
|
|
12
|
+
export const networkRefused = (host) => new Error(`a test tried to reach ${host} — tests use a local server or a scripted adapter; ` +
|
|
13
|
+
"the one test that must reach the network calls onTestFinished(allowNetwork())");
|
|
14
|
+
const refuseUnlessLocal = (host) => {
|
|
15
|
+
if (state().allowed > 0 || LOCAL.has(host.toLowerCase()))
|
|
16
|
+
return;
|
|
17
|
+
throw networkRefused(host);
|
|
18
|
+
};
|
|
19
|
+
// `net.connect` hands `Socket#connect` its arguments already normalised into an array.
|
|
20
|
+
const hostOf = (args) => {
|
|
21
|
+
const first = Array.isArray(args[0]) ? args[0][0] : args[0];
|
|
22
|
+
if (typeof first === "object" && first !== null) {
|
|
23
|
+
const options = first;
|
|
24
|
+
if (typeof options.path === "string")
|
|
25
|
+
return undefined;
|
|
26
|
+
return options.host || "localhost";
|
|
27
|
+
}
|
|
28
|
+
if (typeof first === "number" || (typeof first === "string" && /^\d+$/.test(first)))
|
|
29
|
+
return typeof args[1] === "string" && args[1] !== "" ? args[1] : "localhost";
|
|
30
|
+
return undefined;
|
|
31
|
+
};
|
|
32
|
+
const NETWORK_SCHEMES = new Set(["http:", "https:", "ws:", "wss:"]);
|
|
33
|
+
// `data:` and `blob:` URLs open no connection and have no host.
|
|
34
|
+
const hostOfUrl = (input) => {
|
|
35
|
+
const url = new URL(input instanceof Request ? input.url : String(input));
|
|
36
|
+
return NETWORK_SCHEMES.has(url.protocol) ? url.hostname : undefined;
|
|
37
|
+
};
|
|
38
|
+
const hostOfRequest = (args) => {
|
|
39
|
+
const [first, second] = args;
|
|
40
|
+
const fromUrl = typeof first === "string" || first instanceof URL ? new URL(first).hostname : undefined;
|
|
41
|
+
const options = [first, second].find((arg) => typeof arg === "object" && arg !== null && !(arg instanceof URL));
|
|
42
|
+
if (options?.socketPath)
|
|
43
|
+
return undefined;
|
|
44
|
+
return options?.hostname || options?.host || fromUrl || "localhost";
|
|
45
|
+
};
|
|
46
|
+
// The agent opens the socket on a later tick, where a throw from `Socket#connect` lands as an
|
|
47
|
+
// uncaught exception; checked here, the caller of `request` gets it.
|
|
48
|
+
const guardRequests = (module) => {
|
|
49
|
+
for (const name of ["request", "get"]) {
|
|
50
|
+
const real = module[name];
|
|
51
|
+
module[name] = ((...args) => {
|
|
52
|
+
const host = hostOfRequest(args);
|
|
53
|
+
if (host !== undefined)
|
|
54
|
+
refuseUnlessLocal(host);
|
|
55
|
+
return real(...args);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Refuses every outbound connection except to this machine, before any name is looked up.
|
|
61
|
+
* `Socket#connect` is what `net`, `tls`, `http(s)` and Node's own `fetch` all end in; `http(s)`,
|
|
62
|
+
* `fetch` and `WebSocket` are checked first as well, because through them a refused socket surfaces
|
|
63
|
+
* only as "fetch failed", an error event or an uncaught exception, and Bun's `fetch` skips `net`.
|
|
64
|
+
* Installed once per worker and never removed: a worker that runs tests never needs the network.
|
|
65
|
+
*/
|
|
66
|
+
export const installNetworkGuard = () => {
|
|
67
|
+
const guard = state();
|
|
68
|
+
if (guard.installed)
|
|
69
|
+
return;
|
|
70
|
+
guard.installed = true;
|
|
71
|
+
const connect = net.Socket.prototype.connect;
|
|
72
|
+
net.Socket.prototype.connect = function (...args) {
|
|
73
|
+
const host = hostOf(args);
|
|
74
|
+
if (host !== undefined)
|
|
75
|
+
refuseUnlessLocal(host);
|
|
76
|
+
return connect.apply(this, args);
|
|
77
|
+
};
|
|
78
|
+
guardRequests(http);
|
|
79
|
+
guardRequests(https);
|
|
80
|
+
syncBuiltinESMExports();
|
|
81
|
+
const realFetch = globalThis.fetch;
|
|
82
|
+
if (realFetch)
|
|
83
|
+
globalThis.fetch = async (input, init) => {
|
|
84
|
+
const host = hostOfUrl(input);
|
|
85
|
+
if (host !== undefined)
|
|
86
|
+
refuseUnlessLocal(host);
|
|
87
|
+
return realFetch(input, init);
|
|
88
|
+
};
|
|
89
|
+
const RealWebSocket = globalThis.WebSocket;
|
|
90
|
+
if (RealWebSocket)
|
|
91
|
+
globalThis.WebSocket = new Proxy(RealWebSocket, {
|
|
92
|
+
construct(target, args, newTarget) {
|
|
93
|
+
const host = hostOfUrl(args[0]);
|
|
94
|
+
if (host !== undefined)
|
|
95
|
+
refuseUnlessLocal(host);
|
|
96
|
+
return Reflect.construct(target, args, newTarget);
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Lets the network through until the returned function is called:
|
|
102
|
+
* `onTestFinished(allowNetwork())`. For the rare test whose subject is the network itself.
|
|
103
|
+
*/
|
|
104
|
+
export const allowNetwork = () => {
|
|
105
|
+
state().allowed++;
|
|
106
|
+
let restored = false;
|
|
107
|
+
return () => {
|
|
108
|
+
if (restored)
|
|
109
|
+
return;
|
|
110
|
+
restored = true;
|
|
111
|
+
state().allowed--;
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=network.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/testing/network.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface Sandbox {
|
|
2
|
+
dir: string;
|
|
3
|
+
/** Puts every variable back as it was and removes the directory. */
|
|
4
|
+
restore(): void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Points everything a test could write to at a fresh directory: the temporary folder, the home
|
|
8
|
+
* folder and its XDG and Windows folders, and every `<APP>_CONFIG_DIR`, `_STATE_DIR` and
|
|
9
|
+
* `_CACHE_DIR` already set. One that is not set falls back to the sandboxed home, so a CLI needs no
|
|
10
|
+
* list of its own prefixes; one set in the developer's shell would otherwise point at the real one.
|
|
11
|
+
*/
|
|
12
|
+
export declare const enterSandbox: (env?: NodeJS.ProcessEnv) => Sandbox;
|
|
13
|
+
export declare const REAL_KEYRING_REACHED = "a test reached the real OS keyring \u2014 pass memoryKeyring() instead";
|
|
14
|
+
/**
|
|
15
|
+
* `systemKeyring` loads `@napi-rs/keyring` through `createRequire`, which `vi.mock` does not
|
|
16
|
+
* intercept, so the stand-in goes into the CommonJS require cache. Resolved from here (the copy
|
|
17
|
+
* `keyring.ts` loads) and from the working directory (a CLI's own copy). Never removed.
|
|
18
|
+
*/
|
|
19
|
+
export declare const installThrowingKeyring: () => void;
|
|
20
|
+
//# sourceMappingURL=sandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/testing/sandbox.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,oEAAoE;IACpE,OAAO,IAAI,IAAI,CAAA;CAChB;AAID;;;;;GAKG;AACH,eAAO,MAAM,YAAY,SAAS,MAAM,CAAC,UAAU,KAAiB,OAkCnE,CAAA;AAED,eAAO,MAAM,oBAAoB,2EAAsE,CAAA;AAQvG;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,QAAO,IAgBzC,CAAA"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { mkdirSync, mkdtempSync, rmSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
const OVERRIDE = /_(CONFIG|STATE|CACHE)_DIR$/;
|
|
6
|
+
/**
|
|
7
|
+
* Points everything a test could write to at a fresh directory: the temporary folder, the home
|
|
8
|
+
* folder and its XDG and Windows folders, and every `<APP>_CONFIG_DIR`, `_STATE_DIR` and
|
|
9
|
+
* `_CACHE_DIR` already set. One that is not set falls back to the sandboxed home, so a CLI needs no
|
|
10
|
+
* list of its own prefixes; one set in the developer's shell would otherwise point at the real one.
|
|
11
|
+
*/
|
|
12
|
+
export const enterSandbox = (env = process.env) => {
|
|
13
|
+
const dir = mkdtempSync(join(tmpdir(), "wirecat-test-"));
|
|
14
|
+
const home = join(dir, "home");
|
|
15
|
+
mkdirSync(home);
|
|
16
|
+
const wanted = {
|
|
17
|
+
TMPDIR: dir,
|
|
18
|
+
TMP: dir,
|
|
19
|
+
TEMP: dir,
|
|
20
|
+
HOME: home,
|
|
21
|
+
USERPROFILE: home,
|
|
22
|
+
XDG_CONFIG_HOME: join(home, ".config"),
|
|
23
|
+
XDG_DATA_HOME: join(home, ".local", "share"),
|
|
24
|
+
XDG_STATE_HOME: join(home, ".local", "state"),
|
|
25
|
+
XDG_CACHE_HOME: join(home, ".cache"),
|
|
26
|
+
APPDATA: join(home, "AppData", "Roaming"),
|
|
27
|
+
LOCALAPPDATA: join(home, "AppData", "Local"),
|
|
28
|
+
};
|
|
29
|
+
for (const key of Object.keys(env))
|
|
30
|
+
if (OVERRIDE.test(key) || key === "MESSAGING_STORE")
|
|
31
|
+
wanted[key] = join(dir, "env", key);
|
|
32
|
+
const previous = Object.keys(wanted).map((key) => [key, env[key]]);
|
|
33
|
+
Object.assign(env, wanted);
|
|
34
|
+
return {
|
|
35
|
+
dir,
|
|
36
|
+
restore: () => {
|
|
37
|
+
for (const [key, value] of previous) {
|
|
38
|
+
if (value === undefined)
|
|
39
|
+
delete env[key];
|
|
40
|
+
else
|
|
41
|
+
env[key] = value;
|
|
42
|
+
}
|
|
43
|
+
rmSync(dir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
export const REAL_KEYRING_REACHED = "a test reached the real OS keyring — pass memoryKeyring() instead";
|
|
48
|
+
class ThrowingEntry {
|
|
49
|
+
constructor() {
|
|
50
|
+
throw new Error(REAL_KEYRING_REACHED);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* `systemKeyring` loads `@napi-rs/keyring` through `createRequire`, which `vi.mock` does not
|
|
55
|
+
* intercept, so the stand-in goes into the CommonJS require cache. Resolved from here (the copy
|
|
56
|
+
* `keyring.ts` loads) and from the working directory (a CLI's own copy). Never removed.
|
|
57
|
+
*/
|
|
58
|
+
export const installThrowingKeyring = () => {
|
|
59
|
+
const resolvers = [createRequire(import.meta.url), createRequire(join(process.cwd(), "package.json"))];
|
|
60
|
+
for (const require of resolvers) {
|
|
61
|
+
let path;
|
|
62
|
+
try {
|
|
63
|
+
path = require.resolve("@napi-rs/keyring");
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
require.cache[path] = {
|
|
69
|
+
id: path,
|
|
70
|
+
filename: path,
|
|
71
|
+
loaded: true,
|
|
72
|
+
exports: { Entry: ThrowingEntry },
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/testing/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAQhC,MAAM,QAAQ,GAAG,4BAA4B,CAAA;AAE7C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG,EAAW,EAAE;IAC5E,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAA;IACxD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IAC9B,SAAS,CAAC,IAAI,CAAC,CAAA;IAEf,MAAM,MAAM,GAA2B;QACrC,MAAM,EAAE,GAAG;QACX,GAAG,EAAE,GAAG;QACR,IAAI,EAAE,GAAG;QACT,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,IAAI;QACjB,eAAe,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;QACtC,aAAa,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC;QAC5C,cAAc,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC;QAC7C,cAAc,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC;QACpC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC;QACzC,YAAY,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC;KAC7C,CAAA;IACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QAChC,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,iBAAiB;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,CAAA;IAE1F,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAU,CAAC,CAAA;IAC3E,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IAE1B,OAAO;QACL,GAAG;QACH,OAAO,EAAE,GAAG,EAAE;YACZ,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACpC,IAAI,KAAK,KAAK,SAAS;oBAAE,OAAO,GAAG,CAAC,GAAG,CAAC,CAAA;;oBACnC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;YACvB,CAAC;YACD,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAA;QAC/E,CAAC;KACF,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,mEAAmE,CAAA;AAEvG,MAAM,aAAa;IACjB;QACE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;IACvC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAS,EAAE;IAC/C,MAAM,SAAS,GAAG,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC,CAAA;IACtG,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;QAChC,IAAI,IAAY,CAAA;QAChB,IAAI,CAAC;YACH,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAA;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,SAAQ;QACV,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG;YACpB,EAAE,EAAE,IAAI;YACR,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE;SACN,CAAA;IAC/B,CAAC;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/testing/setup.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { afterAll } from "vitest";
|
|
2
|
+
import { installNetworkGuard } from "./network.js";
|
|
3
|
+
import { enterSandbox, installThrowingKeyring } from "./sandbox.js";
|
|
4
|
+
/**
|
|
5
|
+
* One vitest `setupFiles` entry for every WireCat CLI: `setupFiles: ["@wirecat/cli-base/testing/setup"]`.
|
|
6
|
+
* Each test file gets its own sandbox directory, removed when the file is done; the real keyring and
|
|
7
|
+
* the network stay out of reach for the whole worker.
|
|
8
|
+
*/
|
|
9
|
+
const sandbox = enterSandbox();
|
|
10
|
+
installThrowingKeyring();
|
|
11
|
+
installNetworkGuard();
|
|
12
|
+
afterAll(() => sandbox.restore());
|
|
13
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/testing/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAEnE;;;;GAIG;AACH,MAAM,OAAO,GAAG,YAAY,EAAE,CAAA;AAC9B,sBAAsB,EAAE,CAAA;AACxB,mBAAmB,EAAE,CAAA;AAErB,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA"}
|
package/docs/standards/README.md
CHANGED
|
@@ -27,13 +27,13 @@ rules it keeps. A new CLI is ready for its first release when every check under
|
|
|
27
27
|
|---|---|---:|---|
|
|
28
28
|
| [Toolchain](toolchain.md) | `TOOL` | 19 | TypeScript, Biome, grit plugins, size caps, import cycles, spelling, Markdown |
|
|
29
29
|
| [Layout](layout.md) | `LAY` | 9 | Repository layout, entry points, exports, file size, one job per file, splitting a unit |
|
|
30
|
-
| [Commands](commands.md) | `CMD` |
|
|
30
|
+
| [Commands](commands.md) | `CMD` | 28 | Paths, vocabulary, flags, arguments, effects, lifetime, query, help, external references |
|
|
31
31
|
| [Output](output.md) | `OUT` | 22 | Data on stdout only, envelopes, errors, exit codes, partial answers, projection |
|
|
32
32
|
| [MCP](mcp.md) | `MCP` | 12 | The MCP tools, how they come from commands, what each permission shows |
|
|
33
33
|
| [Accounts](accounts.md) | `ACCT` | 10 | The explicit profile, reads across accounts, scope flags |
|
|
34
34
|
| [Permissions](permissions.md) | `PERM` | 21 | Levels, keys, defaults, hard limits, the write guard and its journal |
|
|
35
35
|
| [Architecture](architecture.md) | `ARCH` | 16 | Layers, dependency direction, vendor types, what goes in which package |
|
|
36
|
-
| [Lifecycle](lifecycle.md) | `LIFE` |
|
|
36
|
+
| [Lifecycle](lifecycle.md) | `LIFE` | 13 | Opening late, who closes, one-shot exits, long-running commands, the `serve` relay, resumable syncs |
|
|
37
37
|
| [Store](store.md) | `STORE` | 14 | Store areas, account scope, migrations, test isolation |
|
|
38
38
|
| [Testing](testing.md) | `TEST` | 17 | Sandbox, no network, no real waits, leak tests, coverage, contracts, test matrix, parity |
|
|
39
39
|
| [Security](security.md) | `SECR` | 19 | Secrets, logs, keyring, argv, error text, scanners, workflow hardening, reporting |
|
|
@@ -144,5 +144,6 @@ A read that is not limited to one account reads every account in its scope, and
|
|
|
144
144
|
These documents explain the rules on this page in more detail. Where one of them disagrees with this page, this page
|
|
145
145
|
holds.
|
|
146
146
|
|
|
147
|
-
- [cli-core `STANDARD.md`, "Command names"](https://github.com/WireCatLabs/cli-core/blob/
|
|
147
|
+
- [cli-core `STANDARD.md`, "Command names"](https://github.com/WireCatLabs/cli-core/blob/022f69fb0acc86f6df05e074ec4df1b911ec94c6/docs/dev/STANDARD.md#command-names),
|
|
148
|
+
rule 1, as it stood before these rules moved to this page
|
|
148
149
|
- [cli-core `ARCHITECTURE.md`](https://github.com/WireCatLabs/cli-core/blob/main/docs/dev/ARCHITECTURE.md), on the account-bound store
|
|
@@ -293,6 +293,48 @@ Each of these is set with `annotate(command, { … })` from `@wirecat/cli-base/c
|
|
|
293
293
|
- **Exceptions:** none. Only memo calls `refuseJoinedPath` today; cli-core and the other CLIs do not yet.
|
|
294
294
|
- **Applies to:** all CLIs. **Since:** cli-base 0.41.0. **Rulings:** none.
|
|
295
295
|
|
|
296
|
+
## External references
|
|
297
|
+
|
|
298
|
+
### WC-CMD-28 · Use the external command-line references as a baseline, and keep the project's choices where they differ
|
|
299
|
+
|
|
300
|
+
The references, each for its own part:
|
|
301
|
+
|
|
302
|
+
* [POSIX Utility Conventions, §12](https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap12.html): utility
|
|
303
|
+
syntax, including `--` to end the options. Long options and the nested command tree are the project's own profile,
|
|
304
|
+
not strict POSIX.
|
|
305
|
+
* [GNU Command-Line Interfaces](https://www.gnu.org/prep/standards/html_node/Command_002dLine-Interfaces): long option
|
|
306
|
+
names, `--help` and `--version`.
|
|
307
|
+
* [Command Line Interface Guidelines](https://clig.dev/): discovery, streams, scripting and compatibility. A guide,
|
|
308
|
+
not a certification.
|
|
309
|
+
* [MCP tools specification, 2025-11-25](https://modelcontextprotocol.io/specification/2025-11-25/server/tools): the
|
|
310
|
+
contract of the MCP server, not of the shell grammar ([MCP](mcp.md)).
|
|
311
|
+
* [JSON Schema](https://json-schema.org/specification): the language of machine contracts. A schema says which
|
|
312
|
+
dialect it uses.
|
|
313
|
+
* [Agent Skills specification](https://agentskills.io/specification): how the agent skill is packaged.
|
|
314
|
+
* [Writing effective tools for agents](https://www.anthropic.com/engineering/writing-tools-for-agents), the
|
|
315
|
+
[CLI Agent Spec](https://cli-agent-spec.github.io/) and the
|
|
316
|
+
[Google Workspace CLI agent context](https://github.com/googleworkspace/cli/blob/main/CONTEXT.md): ideas to weigh
|
|
317
|
+
one by one. No conformance level is claimed, and the CLI Agent Spec's exit codes and response envelope are not
|
|
318
|
+
adopted.
|
|
319
|
+
|
|
320
|
+
- **Why:** a person or an agent who knows these conventions can guess most of a WireCat CLI; where the project
|
|
321
|
+
differs, it says so instead of half-following a reference.
|
|
322
|
+
- **Enforced by:** review only.
|
|
323
|
+
- **Example:** `tg --help` and `tg --version` print text on stdout, also when stdout is not a terminal. An agent
|
|
324
|
+
learns a command from `tg commands <path> --json`; help is never a JSON answer. Data and failures follow
|
|
325
|
+
[WC-OUT-4](output.md#wc-out-4--answer-every-json-request-with-one-envelope-a-list-or-one-thing),
|
|
326
|
+
[WC-OUT-14](output.md#wc-out-14--print-a-failure-in-machine-mode-as-one-json-object-on-stderr-with-stdout-empty) and
|
|
327
|
+
[WC-OUT-18](output.md#wc-out-18--exit-with-cli-bases-code-for-each-kind-of-failure), prompts follow
|
|
328
|
+
[WC-CMD-15](#wc-cmd-15--never-prompt-when-no-person-can-answer), and a renamed path keeps no alias
|
|
329
|
+
([WC-CMD-8](#wc-cmd-8--keep-no-aliases-a-renamed-path-stops-working-in-the-release-that-renames-it)), unlike the
|
|
330
|
+
deprecation advice of the Command Line Interface Guidelines. A read may have documented local effects, such as storing what it read or recording a failed
|
|
331
|
+
run, so a failed command does not promise that it wrote nothing. A write is never retried on its own, and a tool's
|
|
332
|
+
whole payload is never logged. The `stats` root and its resources are the project's own choice.
|
|
333
|
+
- **Exceptions:** the CLI Agent Spec's rule that help goes to stderr when stdout is not a terminal is not adopted. The
|
|
334
|
+
Agent Client Protocol links an editor to a coding agent; a WireCat CLI is a tool an agent calls, so it adds no
|
|
335
|
+
requirement.
|
|
336
|
+
- **Applies to:** all CLIs. **Since:** cli-base 0.44.0. **Rulings:** none.
|
|
337
|
+
|
|
296
338
|
## Sources
|
|
297
339
|
|
|
298
340
|
These documents explain the rules on this page in more detail. Where one of them disagrees with this page, this page
|
|
@@ -301,3 +343,4 @@ holds.
|
|
|
301
343
|
- [cli-core `STANDARD.md`](https://github.com/WireCatLabs/cli-core/blob/main/docs/dev/STANDARD.md): command names, agent
|
|
302
344
|
execution contract, help text
|
|
303
345
|
- [cli-base API reference](https://github.com/WireCatLabs/cli-base/blob/main/docs/REFERENCE.md)
|
|
346
|
+
- [cli-core `STANDARD.md`, "External references and our adoption profile"](https://github.com/WireCatLabs/cli-core/blob/9be227198793fabf506ee946b10aaad94d84d519/docs/dev/STANDARD.md#external-references-and-our-adoption-profile)
|
package/docs/standards/docs.md
CHANGED
|
@@ -150,8 +150,13 @@ Rule ids on this page are `WC-DOC-<n>`. How to read a rule, how ids work and whi
|
|
|
150
150
|
- **Example:** `### Added`, `### Changed — may break callers`, `### Fixed`, `### Security`, `### Removed`. max-cli
|
|
151
151
|
uses this fixed Russian rendering: `Что нового`, `Изменено — может сломать скрипты`, `Исправлено`, `Безопасность`,
|
|
152
152
|
`Удалено`.
|
|
153
|
-
- **Exceptions:**
|
|
154
|
-
and
|
|
153
|
+
- **Exceptions:** a released section keeps the headings it was released with, because it is never edited
|
|
154
|
+
([WC-DOC-20](#wc-doc-20--a-released-section-is-frozen-and-a-new-entry-goes-under-an-existing-heading)). A CLI that
|
|
155
|
+
moves to this set puts its last version with the old headings in its changelog rules as
|
|
156
|
+
`legacyHeadingsThrough: "<version>"`, and the check skips heading names and repeats in every section at or below
|
|
157
|
+
that version. tg-cli keeps the old headings up to 0.69.0, still with its own copy of that rename. memo still
|
|
158
|
+
writes `Changed — may break scripts`, `Documentation` and `Deprecated`, and drive writes `Changed`. Neither runs
|
|
159
|
+
this check yet; they move to this set.
|
|
155
160
|
- **Applies to:** all CLIs and shared libraries. **Since:** cli-base 0.41.0. **Rulings:** none.
|
|
156
161
|
|
|
157
162
|
### WC-DOC-16 · A change a caller may notice goes under "Changed — may break callers"
|
package/docs/standards/layout.md
CHANGED
|
@@ -55,8 +55,9 @@ Rule ids on this page are `WC-LAY-<n>`. How to read a rule, how ids work and whi
|
|
|
55
55
|
- **Why:** everything under `src/` of a library is compiled into `dist/` and published, so a test helper there ships
|
|
56
56
|
to every user.
|
|
57
57
|
- **Enforced by:** review only.
|
|
58
|
-
- **Example:** cli-base
|
|
59
|
-
their own tests is a public entry point instead, such as `@wirecat/cli-base/testing
|
|
58
|
+
- **Example:** a helper only cli-base's own tests use goes in `test/`, not in `src/`. A helper that callers also use
|
|
59
|
+
in their own tests is a public entry point instead, such as `@wirecat/cli-base/testing` and the shared test setup
|
|
60
|
+
`@wirecat/cli-base/testing/setup`.
|
|
60
61
|
- **Exceptions:** a CLI's colocated `*.test.ts` files stay in `src/`, because its `tsconfig.json` excludes them from
|
|
61
62
|
the build.
|
|
62
63
|
- **Applies to:** cli-base, cli-core and cli-testing. **Since:** cli-base 0.41.0. **Rulings:** none.
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
## Scope
|
|
4
4
|
|
|
5
5
|
How a process starts and ends: nothing opens before it is needed, the code that opens a resource closes it, a
|
|
6
|
-
one-shot command exits, everything that was opened is closed before the answer is printed,
|
|
7
|
-
connection is held by one process only.
|
|
6
|
+
one-shot command exits, everything that was opened is closed before the answer is printed, an exclusive
|
|
7
|
+
connection is held by one process only, and a long sync carries on after a kill.
|
|
8
8
|
|
|
9
9
|
Rule ids on this page are `WC-LIFE-<n>`. How to read a rule, how ids work and which rule wins are in the
|
|
10
10
|
[index](README.md). How a command declares `lifetime` and `cooperative` is on the [commands](commands.md) page. The
|
|
@@ -132,6 +132,48 @@ waits for a person, such as a login).
|
|
|
132
132
|
- **Applies to:** messenger CLIs with an exclusive connection (wa today). **Since:** cli-base 0.41.0.
|
|
133
133
|
**Rulings:** NEED-1389.
|
|
134
134
|
|
|
135
|
+
## Resumable syncs
|
|
136
|
+
|
|
137
|
+
A long sync — a mailbox, a chat history, a Drive folder, a recording archive — is stopped by a kill, a reboot or a
|
|
138
|
+
provider's limit as often as it ends. These three rules make the next run carry on.
|
|
139
|
+
|
|
140
|
+
### WC-LIFE-12 · Save a long sync's work per item or per page, so a kill loses nothing saved
|
|
141
|
+
|
|
142
|
+
- **Why:** a sync that saves only at the end loses hours of work to one kill.
|
|
143
|
+
- **Enforced by:** review only.
|
|
144
|
+
- **Example:** each page of a chat's history goes into the store in its own transaction as it arrives, and the
|
|
145
|
+
position moves with it. drive saves its first folder walk in its state file as it goes.
|
|
146
|
+
- **Exceptions:** none.
|
|
147
|
+
- **Applies to:** every CLI with a sync. **Since:** cli-base 0.44.0. **Rulings:** none.
|
|
148
|
+
|
|
149
|
+
### WC-LIFE-13 · A rerun goes on from where the last run stopped, and starting over is an option
|
|
150
|
+
|
|
151
|
+
- **Why:** a rerun that lists or pages everything again repeats the work the kill cut short.
|
|
152
|
+
- **Enforced by:** `drive-cli: src/sync.test.ts` · `cli-memo: src/mail/import.test.ts`.
|
|
153
|
+
- **Example:** a rerun skips what is stored and does not redo the listing or paging that got there. The position
|
|
154
|
+
lives in the store when the store already holds it: tg and max keep the held stretch of each chat, so
|
|
155
|
+
`messages sync --all` skips a chat held to its newest message; memo keeps a resume point per mail folder; zm keeps
|
|
156
|
+
the checkpoint of `recordings sync`. Otherwise it lives in a checkpoint file,
|
|
157
|
+
`<state>/checkpoints/<profile>/<job>.json`, written with `saveCheckpoint` and read with `readCheckpoint` from
|
|
158
|
+
`@wirecat/cli-core/background`. The write is atomic, and a torn file reads as no checkpoint: one run from the start,
|
|
159
|
+
never a failed run. Starting over is `--rescan`, as in `drive personal sync --rescan`; it is in the cli-base flag
|
|
160
|
+
registry.
|
|
161
|
+
- **Exceptions:** none. No CLI uses the checkpoint file yet; drive keeps its position in its own state file.
|
|
162
|
+
- **Applies to:** every CLI with a sync. **Since:** cli-base 0.44.0. **Rulings:** none.
|
|
163
|
+
|
|
164
|
+
### WC-LIFE-14 · A sync's status command says how far it is, in one shape
|
|
165
|
+
|
|
166
|
+
- **Why:** a person or an agent deciding whether to wait or rerun needs the same answer from every CLI.
|
|
167
|
+
- **Enforced by:** `cli-core: src/background/checkpoints.test.ts`.
|
|
168
|
+
- **Example:** `progressOf` from `@wirecat/cli-core/background` builds
|
|
169
|
+
`{ job, profile, done, total, remaining, state, updated_at, cursor_age_ms }`, and `progressLine` prints it on one
|
|
170
|
+
line in text. `state` is `partial` or `complete`; `total` and `remaining` are `null` when the source does not say how
|
|
171
|
+
much there is. memo's `mail status` answers with it, and the messenger CLIs' `store jobs show` answers with it as
|
|
172
|
+
`progress`.
|
|
173
|
+
- **Exceptions:** none. drive and zm print no progress shape yet; that is a known gap. Whether the last scheduled run
|
|
174
|
+
failed is a different question, answered by `recordRun` and `failingNotice` in cli-core's schedules.
|
|
175
|
+
- **Applies to:** every CLI with a sync. **Since:** cli-base 0.44.0. **Rulings:** none.
|
|
176
|
+
|
|
135
177
|
## Sources
|
|
136
178
|
|
|
137
179
|
These documents explain the rules on this page in more detail. Where one of them disagrees with this page, this page
|
|
@@ -141,3 +183,4 @@ holds.
|
|
|
141
183
|
- [cli-core `STANDARD.md`](https://github.com/WireCatLabs/cli-core/blob/main/docs/dev/STANDARD.md), "Agent execution
|
|
142
184
|
contract"
|
|
143
185
|
- [cli-base API reference](https://github.com/WireCatLabs/cli-base/blob/main/docs/REFERENCE.md)
|
|
186
|
+
- [cli-core `STANDARD.md`, "Resumable syncs"](https://github.com/WireCatLabs/cli-core/blob/9be227198793fabf506ee946b10aaad94d84d519/docs/dev/STANDARD.md#resumable-syncs)
|
package/docs/standards/store.md
CHANGED
|
@@ -157,10 +157,11 @@ Related pages: which account a read covers, and how a read across accounts is as
|
|
|
157
157
|
### WC-STORE-14 · Tests never open the owner's store
|
|
158
158
|
|
|
159
159
|
- **Why:** migrations only go forward; a test that opened the real file would migrate it, and nothing undoes that.
|
|
160
|
-
- **Enforced by:**
|
|
161
|
-
- **Example:** the
|
|
162
|
-
|
|
163
|
-
|
|
160
|
+
- **Enforced by:** `src/testing/sandbox.test.ts`.
|
|
161
|
+
- **Example:** the shared setup, `setupFiles: ["@wirecat/cli-base/testing/setup"]`, points `MESSAGING_STORE`,
|
|
162
|
+
`WIRECAT_STATE_DIR` and every `<APP>_CONFIG_DIR`, `_STATE_DIR` and `_CACHE_DIR` that is set at a temporary
|
|
163
|
+
directory before any test runs, and the home folder with them, so one that is not set lands there too. No CLI
|
|
164
|
+
uses it yet: cli-core's own sandbox still sets these variables for each app prefix its tests define. A test that needs its own store is
|
|
164
165
|
[WC-TEST-9](testing.md#wc-test-9--give-each-test-its-own-profile-or-its-own-store). The rest of the sandbox is
|
|
165
166
|
[WC-TEST-1](testing.md#wc-test-1--point-every-path-a-test-could-write-at-a-temporary-directory).
|
|
166
167
|
- **Exceptions:** none.
|
|
@@ -29,36 +29,46 @@ and which run after merge is in [CI](ci.md).
|
|
|
29
29
|
### WC-TEST-1 · Point every path a test could write at a temporary directory
|
|
30
30
|
|
|
31
31
|
- **Why:** one test that falls back to a default path writes into the owner's config, state, cache or store.
|
|
32
|
-
- **Enforced by:**
|
|
33
|
-
- **Example:**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
- **Enforced by:** `src/testing/sandbox.test.ts`.
|
|
33
|
+
- **Example:** a CLI adopts the shared setup with one line in `vitest.config.ts`:
|
|
34
|
+
`setupFiles: ["@wirecat/cli-base/testing/setup"]`. It holds for every test file, including the next one. Each
|
|
35
|
+
file gets a fresh directory: `TMPDIR`, `TMP`, `TEMP`, `HOME`, `USERPROFILE`, the XDG and Windows folders, and
|
|
36
|
+
every `<APP>_CONFIG_DIR`, `_STATE_DIR` and `_CACHE_DIR` already set, with the store variables
|
|
37
|
+
([WC-STORE-14](store.md#wc-store-14--tests-never-open-the-owners-store)), point into it. One that is not set falls
|
|
38
|
+
back to the sandboxed home. When the file is done, after its own hooks have closed their resources, the setup
|
|
39
|
+
restores the variables and removes the directory. A CLI's own setup file, listed after the shared one, adds only
|
|
40
|
+
what is its own, such as a default profile.
|
|
38
41
|
- **Exceptions:** keep coverage reports and debug traces outside the sandbox, with bounded retention. Never clean
|
|
39
42
|
another session's scratch directory as test teardown.
|
|
40
|
-
- **Applies to:** all CLIs and the shared packages.
|
|
41
|
-
temporary directory. **Since:** cli-base 0.41.0. **Rulings:** none.
|
|
43
|
+
- **Applies to:** all CLIs and the shared packages. cli-base uses the shared setup; the CLIs keep their own sandboxes
|
|
44
|
+
for now. drive has none yet, and zoom's moves only the temporary directory. **Since:** cli-base 0.41.0. **Rulings:** none.
|
|
42
45
|
|
|
43
46
|
### WC-TEST-2 · No test reaches the real keyring
|
|
44
47
|
|
|
45
48
|
- **Why:** the owner's tokens live in the real keychain, and one test that forgets an option would write there.
|
|
46
49
|
- **Enforced by:** `src/keyring.test.ts`.
|
|
47
|
-
- **Example:** every test passes `memoryKeyring()` from `@wirecat/cli-base/testing`.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
- **Example:** every test passes `memoryKeyring()` from `@wirecat/cli-base/testing`. The shared setup
|
|
51
|
+
(`@wirecat/cli-base/testing/setup`, [WC-TEST-1](#wc-test-1--point-every-path-a-test-could-write-at-a-temporary-directory))
|
|
52
|
+
also replaces `@napi-rs/keyring` with a module that throws, so a forgotten option fails the test instead of
|
|
53
|
+
reaching the keychain, and `src/keyring.test.ts` asserts that `systemKeyring` throws under it.
|
|
54
|
+
- **Exceptions:** none. Until a CLI adopts the shared setup, its sandbox does not replace `@napi-rs/keyring`; tg and
|
|
55
|
+
max only scope the keyring entry through environment variables.
|
|
52
56
|
- **Applies to:** all CLIs and the shared packages. **Since:** cli-base 0.41.0. **Rulings:** none.
|
|
53
57
|
|
|
54
58
|
### WC-TEST-3 · No test contacts a provider or the network
|
|
55
59
|
|
|
56
60
|
- **Why:** a test that reaches the network is slow, flaky, and can act on a real account.
|
|
57
|
-
- **Enforced by:** `max-cli: src/testing/unscripted.ts`.
|
|
58
|
-
- **Example:**
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
- **Enforced by:** `src/testing/network.test.ts`, `max-cli: src/testing/unscripted.ts`.
|
|
62
|
+
- **Example:** the shared setup
|
|
63
|
+
([WC-TEST-1](#wc-test-1--point-every-path-a-test-could-write-at-a-temporary-directory)) refuses every connection
|
|
64
|
+
to anything but `localhost`, `127.0.0.1` and `::1` before a name is looked up: `net` and `tls` connects,
|
|
65
|
+
`http(s)` requests, `fetch` and `WebSocket` throw an error that names the host. A test talks to a local server or
|
|
66
|
+
a scripted adapter instead. max-cli's `src/testing/mock-max.ts` scripts the service: an answer per request, a
|
|
67
|
+
refusal, or silence to test a timeout, and a request with no scripted answer fails the test that sent it. tg's
|
|
68
|
+
`scripted({...})` adapter does the same job.
|
|
69
|
+
- **Exceptions:** a test whose subject is the network itself calls `onTestFinished(allowNetwork())`, with
|
|
70
|
+
`allowNetwork` from `@wirecat/cli-base/testing`; the guard is back for the next test. Until a CLI adopts the shared
|
|
71
|
+
setup it has no global guard; max's unscripted check and tg's scripted adapter cover only their own service.
|
|
62
72
|
- **Applies to:** all CLIs and the shared packages. **Since:** cli-base 0.41.0. **Rulings:** none.
|
|
63
73
|
|
|
64
74
|
### WC-TEST-4 · Give a command that must not connect an adapter that throws
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wirecat/cli-base",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.43.0",
|
|
4
4
|
"description": "The parts every command line tool needs: output modes, terminal rendering, error model, exit codes, credentials, clocks",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|
|
@@ -33,6 +33,10 @@
|
|
|
33
33
|
"types": "./dist/testing/index.d.ts",
|
|
34
34
|
"default": "./dist/testing/index.js"
|
|
35
35
|
},
|
|
36
|
+
"./testing/setup": {
|
|
37
|
+
"types": "./dist/testing/setup.d.ts",
|
|
38
|
+
"default": "./dist/testing/setup.js"
|
|
39
|
+
},
|
|
36
40
|
"./http": {
|
|
37
41
|
"types": "./dist/http/index.d.ts",
|
|
38
42
|
"default": "./dist/http/index.js"
|
|
@@ -132,11 +136,15 @@
|
|
|
132
136
|
"access": "public"
|
|
133
137
|
},
|
|
134
138
|
"peerDependencies": {
|
|
135
|
-
"commander": ">=15"
|
|
139
|
+
"commander": ">=15",
|
|
140
|
+
"vitest": ">=5"
|
|
136
141
|
},
|
|
137
142
|
"peerDependenciesMeta": {
|
|
138
143
|
"commander": {
|
|
139
144
|
"optional": true
|
|
145
|
+
},
|
|
146
|
+
"vitest": {
|
|
147
|
+
"optional": true
|
|
140
148
|
}
|
|
141
149
|
}
|
|
142
150
|
}
|