@orkestrel/scaffold 0.0.108 → 0.0.109
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/agents/skills/orkestrel-dispatch/scripts/bench.js +326 -91
- package/dist/agents/skills/orkestrel-dispatch/scripts/brief.js +110 -14
- package/dist/agents/skills/orkestrel-dispatch/scripts/chain.js +280 -0
- package/dist/agents/skills/orkestrel-dispatch/scripts/cite.js +188 -26
- package/dist/agents/skills/orkestrel-dispatch/scripts/launch.js +142 -43
- package/dist/agents/skills/orkestrel-dispatch/scripts/login.js +240 -62
- package/dist/agents/skills/orkestrel-dispatch/scripts/patch.js +323 -0
- package/dist/agents/skills/orkestrel-dispatch/scripts/result.js +169 -32
- package/dist/agents/skills/orkestrel-dispatch/scripts/sweep.js +290 -69
- package/dist/agents/skills/orkestrel-falsify/scripts/mutate.js +560 -0
- package/dist/agents/skills/orkestrel-harden/scripts/discovery.js +1052 -205
- package/dist/agents/skills/orkestrel-harden/scripts/measure.js +361 -0
- package/dist/agents/skills/orkestrel-harden/scripts/titles.js +455 -80
- package/dist/agents/skills/orkestrel-parallel/scripts/cases.js +327 -0
- package/dist/agents/skills/orkestrel-publish/scripts/compare.js +298 -51
- package/dist/agents/skills/orkestrel-publish/scripts/pins.js +170 -13
- package/dist/agents/skills/orkestrel-publish/scripts/swap.js +956 -191
- package/dist/agents/skills/orkestrel-publish/scripts/wave.js +707 -112
- package/dist/agents/skills/orkestrel-publish/scripts/window.js +235 -41
- package/dist/agents/skills/orkestrel-scout/scripts/map.js +341 -54
- package/dist/agents/templates/brief.md +1 -1
- package/dist/bin/main.js +51 -46
- package/dist/bin/main.js.map +1 -1
- package/dist/host/AGENTS.md +23 -21
- package/dist/host/agents/orchestration.md +43 -18
- package/dist/host/agents/platforms/windows.md +3 -3
- package/dist/host/agents/skills/orkestrel-align/SKILL.md +10 -13
- package/dist/host/agents/skills/orkestrel-align/references/fleet.md +4 -10
- package/dist/host/agents/skills/orkestrel-align/references/integration.md +1 -1
- package/dist/host/agents/skills/orkestrel-build/SKILL.md +16 -48
- package/dist/host/agents/skills/orkestrel-build/agents/openai.yaml +1 -1
- package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +19 -16
- package/dist/host/agents/skills/orkestrel-debrief/agents/openai.yaml +1 -1
- package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +15 -28
- package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +5 -6
- package/dist/host/agents/skills/orkestrel-debrief/references/retention.md +4 -6
- package/dist/host/agents/skills/orkestrel-dispatch/SKILL.md +31 -20
- package/dist/host/agents/skills/orkestrel-dispatch/references/launch.md +3 -4
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/bench.ts +366 -75
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/brief.ts +126 -16
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/chain.ts +323 -0
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/cite.ts +220 -31
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/launch.ts +176 -33
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/login.ts +294 -59
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/patch.ts +401 -0
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/result.ts +199 -34
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/sweep.ts +330 -69
- package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +10 -8
- package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +1 -5
- package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +1 -1
- package/dist/host/agents/skills/orkestrel-falsify/scripts/mutate.ts +701 -0
- package/dist/host/agents/skills/orkestrel-harden/SKILL.md +16 -12
- package/dist/host/agents/skills/orkestrel-harden/references/bindings.md +23 -81
- package/dist/host/agents/skills/orkestrel-harden/references/centralization.md +4 -5
- package/dist/host/agents/skills/orkestrel-harden/references/contract.md +2 -0
- package/dist/host/agents/skills/orkestrel-harden/references/document.md +33 -0
- package/dist/host/agents/skills/orkestrel-harden/references/equivalence.md +6 -3
- package/dist/host/agents/skills/orkestrel-harden/references/hardening.md +8 -4
- package/dist/host/agents/skills/orkestrel-harden/references/research.md +2 -0
- package/dist/host/agents/skills/orkestrel-harden/scripts/discovery.ts +1272 -279
- package/dist/host/agents/skills/orkestrel-harden/scripts/measure.ts +425 -0
- package/dist/host/agents/skills/orkestrel-harden/scripts/titles.ts +603 -98
- package/dist/host/agents/skills/orkestrel-journey/SKILL.md +75 -98
- package/dist/host/agents/skills/orkestrel-journey/references/captures.md +54 -17
- package/dist/host/agents/skills/orkestrel-journey/references/decide.md +1 -20
- package/dist/host/agents/skills/orkestrel-journey/references/layer.md +21 -31
- package/dist/host/agents/skills/orkestrel-journey/references/styles.md +1 -1
- package/dist/host/agents/skills/orkestrel-parallel/SKILL.md +28 -24
- package/dist/host/agents/skills/orkestrel-parallel/references/claude.md +15 -13
- package/dist/host/agents/skills/orkestrel-parallel/references/codex.md +1 -0
- package/dist/host/agents/skills/orkestrel-parallel/references/cursor.md +13 -13
- package/dist/host/agents/skills/orkestrel-parallel/scripts/cases.ts +389 -0
- package/dist/host/agents/skills/orkestrel-polish/SKILL.md +16 -20
- package/dist/host/agents/skills/orkestrel-polish/references/capture-harness.md +16 -26
- package/dist/host/agents/skills/orkestrel-publish/SKILL.md +12 -26
- package/dist/host/agents/skills/orkestrel-publish/agents/openai.yaml +2 -2
- package/dist/host/agents/skills/orkestrel-publish/references/adopt.md +23 -0
- package/dist/host/agents/skills/orkestrel-publish/references/release.md +4 -4
- package/dist/host/agents/skills/orkestrel-publish/references/wave.md +10 -9
- package/dist/host/agents/skills/orkestrel-publish/references/window.md +20 -25
- package/dist/host/agents/skills/orkestrel-publish/scripts/compare.ts +348 -59
- package/dist/host/agents/skills/orkestrel-publish/scripts/pins.ts +202 -22
- package/dist/host/agents/skills/orkestrel-publish/scripts/swap.ts +1061 -191
- package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +812 -140
- package/dist/host/agents/skills/orkestrel-publish/scripts/window.ts +280 -38
- package/dist/host/agents/skills/orkestrel-scout/SKILL.md +3 -3
- package/dist/host/agents/skills/orkestrel-scout/scripts/map.ts +428 -70
- package/dist/host/agents/templates/brief.md +1 -1
- package/dist/host/agents/transports/claude-cli.md +3 -3
- package/dist/host/agents/transports/codex.md +2 -7
- package/dist/host/agents/transports/cursor.md +2 -3
- package/dist/host/claude/AGENTS.md +2 -2
- package/dist/host/claude/agents/analyst.md +3 -3
- package/dist/host/claude/agents/astra.md +3 -3
- package/dist/host/claude/agents/builder.md +1 -1
- package/dist/host/claude/agents/checker.md +1 -1
- package/dist/host/claude/agents/distiller.md +1 -1
- package/dist/host/claude/agents/grok.md +1 -1
- package/dist/host/claude/agents/opus.md +2 -2
- package/dist/host/claude/agents/orkestrel.md +57 -90
- package/dist/host/claude/agents/researcher.md +1 -1
- package/dist/host/claude/agents/reviewer.md +4 -0
- package/dist/host/claude/agents/scout.md +1 -1
- package/dist/host/claude/agents/verifier.md +1 -1
- package/dist/host/claude/rules/application.md +14 -21
- package/dist/host/claude/rules/architecture.md +34 -44
- package/dist/host/claude/rules/browser.md +3 -4
- package/dist/host/claude/rules/campaign.md +2 -2
- package/dist/host/claude/rules/documentation.md +25 -12
- package/dist/host/claude/rules/names.md +9 -4
- package/dist/host/claude/rules/patterns.md +6 -7
- package/dist/host/claude/rules/portability.md +1 -1
- package/dist/host/claude/rules/quality.md +4 -5
- package/dist/host/claude/rules/styles.md +2 -2
- package/dist/host/claude/rules/tests.md +57 -114
- package/dist/host/claude/rules/typescript.md +7 -9
- package/dist/host/claude/rules/workspace.md +21 -19
- package/dist/host/claude/rules/writing.md +2 -5
- package/dist/host/claude/skills/orkestrel-dispatch/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-harden/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-publish/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-scout/SKILL.md +1 -1
- package/dist/host/codex/agents/analyst.toml +9 -3
- package/dist/host/codex/agents/astra.toml +3 -4
- package/dist/host/codex/agents/builder.toml +1 -1
- package/dist/host/codex/agents/opus.toml +3 -4
- package/dist/host/codex/agents/orkestrel.toml +1 -1
- package/dist/host/codex/agents/researcher.toml +2 -2
- package/dist/host/codex/agents/verifier.toml +1 -1
- package/dist/host/configs/helpers.ts +21 -1
- package/dist/host/configs/policy.ts +299 -15
- package/dist/host/dotfiles/oxlintrc.json +137 -3
- package/dist/host/guides/agent.md +111 -134
- package/dist/host/guides/capture.md +801 -0
- package/dist/host/guides/probe.md +27 -8
- package/dist/host/guides/scaffold.md +96 -18
- package/dist/host/guides/study.md +534 -440
- package/dist/host/guides/test.md +111 -44
- package/dist/host/manifest.json +160 -240
- package/dist/host/tests/config.test.ts +971 -187
- package/dist/host/tests/policy.test.ts +127 -1
- package/dist/host/tests/setupPolicy.ts +893 -33
- package/dist/src/core/index.cjs +214 -86
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +122 -38
- package/dist/src/core/index.d.ts +122 -38
- package/dist/src/core/index.js +209 -85
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +20 -27
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.js +21 -28
- package/dist/src/server/index.js.map +1 -1
- package/package.json +11 -11
- package/dist/agents/skills/orkestrel-dispatch/scripts/helpers.js +0 -283
- package/dist/host/agents/skills/orkestrel-dispatch/references/bench.md +0 -25
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/helpers.ts +0 -333
- package/dist/host/guides/supervisor.md +0 -4890
|
@@ -1,63 +1,227 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// node .agents/skills/orkestrel-publish/scripts/window.ts --login [--wait SECONDS]
|
|
4
|
-
// node .agents/skills/orkestrel-publish/scripts/window.ts --publish DIR... --otp CODE [--json]
|
|
5
|
-
// node .agents/skills/orkestrel-publish/scripts/window.ts --confirm NAME@VERSION... [--wait SECONDS]
|
|
6
|
-
// --whoami reads `npm whoami` once, or polls it every 5 seconds until it answers or the wait ends.
|
|
7
|
-
// --login prints the command the operator runs in a real terminal (npm offers its approval only to a
|
|
8
|
-
// TTY, so no child of this script can hold it), then polls `npm whoami` until it answers or the wait
|
|
9
|
-
// ends. --publish refuses linked worktrees and submodules found at a package or its ancestors,
|
|
10
|
-
// and names a linked worktree's primary clone.
|
|
11
|
-
// It then re-reads `npm whoami` immediately before the first upload and refuses when it
|
|
12
|
-
// answers nothing, then runs `npm publish --ignore-scripts --browser=false --otp=CODE` in each
|
|
13
|
-
// directory back to back under captured pipes (npm's non-TTY guard turns a refused code into
|
|
14
|
-
// EOTP with no prompt, so the path needs no TTY), journals each upload to tmp/units/publish-<name>.log, reads the `+ name@version`
|
|
15
|
-
// acceptance line, stops at the first refusal and names the package to resume from, then confirms
|
|
16
|
-
// each accepted version against the registry. --confirm re-reads the registry for each name@version every 5
|
|
17
|
-
// seconds until it serves the version or the wait (default 120 seconds) ends. Exit 0 when the mode
|
|
18
|
-
// succeeded, 3 when it did not, 64 on usage.
|
|
19
|
-
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, realpathSync, statSync, writeFileSync } from 'node:fs';
|
|
20
3
|
import { dirname, join, resolve } from 'node:path';
|
|
21
|
-
|
|
22
|
-
const POLL_MS = 5_000;
|
|
23
|
-
|
|
24
|
-
|
|
4
|
+
/** Holds the milliseconds between two polls of the registry. */
|
|
5
|
+
export const POLL_MS = 5_000;
|
|
6
|
+
/** Matches the acceptance line `npm publish` prints and captures the name and the version. */
|
|
7
|
+
export const ACCEPTED = /^\+ (\S+)@(\S+)\s*$/mu;
|
|
8
|
+
/** Lists every flag the script reads, value flags and switches alike. */
|
|
9
|
+
export const FLAGS = [
|
|
10
|
+
'--whoami',
|
|
11
|
+
'--login',
|
|
12
|
+
'--publish',
|
|
13
|
+
'--confirm',
|
|
14
|
+
'--wait',
|
|
15
|
+
'--otp',
|
|
16
|
+
'--json',
|
|
17
|
+
];
|
|
18
|
+
/** Holds the usage line the script prints when no mode or two modes were given. */
|
|
19
|
+
export const USAGE = 'usage: window.ts --whoami [--wait SECONDS] | --login [--wait SECONDS] | --publish DIR... --otp CODE [--json] | --confirm NAME@VERSION... [--wait SECONDS]';
|
|
20
|
+
/**
|
|
21
|
+
* Reads the value that follows a flag.
|
|
22
|
+
*
|
|
23
|
+
* @remarks
|
|
24
|
+
* Reads `--flag value` pairs: the first occurrence of a flag wins, a following value that opens
|
|
25
|
+
* with `--` is a missing value, and the `--flag=value` form is not read.
|
|
26
|
+
*
|
|
27
|
+
* @param argv - The arguments after the script path.
|
|
28
|
+
* @param name - The flag, such as `--otp`.
|
|
29
|
+
* @returns The value after the flag, or undefined when the flag is absent, last, or followed by
|
|
30
|
+
* another flag.
|
|
31
|
+
*/
|
|
32
|
+
export function readOption(argv, name) {
|
|
33
|
+
const index = argv.indexOf(name);
|
|
34
|
+
const value = index === -1 ? undefined : argv[index + 1];
|
|
35
|
+
return value === undefined || value.startsWith('--') ? undefined : value;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Names the value flags a caller gave with no value.
|
|
39
|
+
*
|
|
40
|
+
* @param argv - The arguments after the script path.
|
|
41
|
+
* @param names - The flags that take a value.
|
|
42
|
+
* @returns Each named flag that appears last or is followed by another flag, in argument order.
|
|
43
|
+
*/
|
|
44
|
+
export function readMissingFlags(argv, names) {
|
|
45
|
+
return names.filter((name) => argv.includes(name) && readOption(argv, name) === undefined);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Names the flags a caller gave that the script does not read.
|
|
49
|
+
*
|
|
50
|
+
* @remarks
|
|
51
|
+
* Reads the arguments before a bare `--`, which opens a command a script passes on. A `--flag=value`
|
|
52
|
+
* argument is unknown, because the script reads no such form.
|
|
53
|
+
*
|
|
54
|
+
* @param argv - The arguments after the script path.
|
|
55
|
+
* @param flags - Every flag the script reads, value flags and switches alike.
|
|
56
|
+
* @returns Each argument that opens with `--` and is not a read flag, in argument order.
|
|
57
|
+
*/
|
|
58
|
+
export function readUnknownFlags(argv, flags) {
|
|
59
|
+
const end = argv.indexOf('--');
|
|
60
|
+
return (end === -1 ? argv : argv.slice(0, end)).filter((argument) => argument.startsWith('--') && !flags.includes(argument));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Reads the values that follow a flag up to the next flag.
|
|
64
|
+
*
|
|
65
|
+
* @param argv - The arguments after the script path.
|
|
66
|
+
* @param name - The flag, such as `--publish`.
|
|
67
|
+
* @returns The values between the flag and the next `--` argument, empty when the flag is absent.
|
|
68
|
+
*/
|
|
69
|
+
export function readList(argv, name) {
|
|
70
|
+
const index = argv.indexOf(name);
|
|
71
|
+
if (index === -1)
|
|
72
|
+
return [];
|
|
73
|
+
const rest = argv.slice(index + 1);
|
|
74
|
+
const end = rest.findIndex((argument) => argument.startsWith('--'));
|
|
75
|
+
return end === -1 ? rest : rest.slice(0, end);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Parses a whole text as one JSON object.
|
|
79
|
+
*
|
|
80
|
+
* @param text - A JSON document, formatted or not, such as a manifest.
|
|
81
|
+
* @returns The parsed object, or undefined when the text is not a JSON object.
|
|
82
|
+
*/
|
|
83
|
+
export function parseJsonRecord(text) {
|
|
84
|
+
try {
|
|
85
|
+
const parsed = JSON.parse(text);
|
|
86
|
+
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
|
|
87
|
+
return Object.fromEntries(Object.entries(parsed));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch { }
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Reads a string member of a record.
|
|
95
|
+
*
|
|
96
|
+
* @param record - The record, or undefined.
|
|
97
|
+
* @param key - The member name.
|
|
98
|
+
* @returns The string, or undefined when the member is absent or not a string.
|
|
99
|
+
*/
|
|
100
|
+
export function readString(record, key) {
|
|
101
|
+
const value = record?.[key];
|
|
102
|
+
return typeof value === 'string' ? value : undefined;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Resolves the npm command for this host.
|
|
106
|
+
*
|
|
107
|
+
* @remarks
|
|
108
|
+
* The `npm-cli.js` entry beside the running Node binary spawns without a shell on every host; the
|
|
109
|
+
* `npm` shim on Windows is a `.cmd` file that needs one, so that path is the fallback alone.
|
|
110
|
+
*
|
|
111
|
+
* @returns The file to spawn, the arguments that precede npm's own, and whether a shell is needed.
|
|
112
|
+
*/
|
|
113
|
+
export function resolveNpm() {
|
|
114
|
+
const cli = join(dirname(process.execPath), 'node_modules', 'npm', 'bin', 'npm-cli.js');
|
|
115
|
+
if (existsSync(cli))
|
|
116
|
+
return { file: process.execPath, prefix: [cli], shell: false };
|
|
117
|
+
return { file: 'npm', prefix: [], shell: process.platform === 'win32' };
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Runs npm with the given arguments and returns the finished child.
|
|
121
|
+
*
|
|
122
|
+
* @param args - The npm arguments, such as `['whoami']`.
|
|
123
|
+
* @param cwd - The working directory. Default: the current directory.
|
|
124
|
+
* @returns The spawn result with `utf8` stdout and stderr.
|
|
125
|
+
*/
|
|
126
|
+
export function runNpm(args, cwd) {
|
|
127
|
+
const npm = resolveNpm();
|
|
128
|
+
return spawnSync(npm.file, [...npm.prefix, ...args], {
|
|
129
|
+
encoding: 'utf8',
|
|
130
|
+
windowsHide: true,
|
|
131
|
+
shell: npm.shell,
|
|
132
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
133
|
+
...(cwd === undefined ? {} : { cwd }),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Waits for a number of milliseconds.
|
|
138
|
+
*
|
|
139
|
+
* @param ms - The delay.
|
|
140
|
+
* @returns A promise that settles after the delay.
|
|
141
|
+
*/
|
|
142
|
+
export function waitFor(ms) {
|
|
25
143
|
return new Promise((settle) => {
|
|
26
144
|
setTimeout(settle, ms);
|
|
27
145
|
});
|
|
28
146
|
}
|
|
29
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Reads the account `npm whoami` names once.
|
|
149
|
+
*
|
|
150
|
+
* @returns The user name, or undefined when npm exited nonzero or printed nothing.
|
|
151
|
+
*/
|
|
152
|
+
export function readWhoami() {
|
|
30
153
|
const result = runNpm(['whoami']);
|
|
31
154
|
const user = result.stdout.trim();
|
|
32
155
|
return result.status === 0 && user !== '' ? user : undefined;
|
|
33
156
|
}
|
|
34
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Polls `npm whoami` until it answers or the wait ends.
|
|
159
|
+
*
|
|
160
|
+
* @param waitSeconds - How long to keep polling; 0 reads once.
|
|
161
|
+
* @param started - The millisecond the polling began. Default: now.
|
|
162
|
+
* @returns The user name, or undefined when none answered within the wait.
|
|
163
|
+
*/
|
|
164
|
+
export async function pollWhoami(waitSeconds, started = Date.now()) {
|
|
35
165
|
const user = readWhoami();
|
|
36
166
|
if (user !== undefined || Date.now() - started >= waitSeconds * 1000)
|
|
37
167
|
return user;
|
|
38
168
|
await waitFor(POLL_MS);
|
|
39
169
|
return pollWhoami(waitSeconds, started);
|
|
40
170
|
}
|
|
41
|
-
|
|
171
|
+
/**
|
|
172
|
+
* Checks whether the registry serves one version of a package.
|
|
173
|
+
*
|
|
174
|
+
* @param name - The package name.
|
|
175
|
+
* @param version - The version.
|
|
176
|
+
* @returns True if `npm view` reads exactly that version; false otherwise.
|
|
177
|
+
*/
|
|
178
|
+
export function readServed(name, version) {
|
|
42
179
|
const result = runNpm(['view', `${name}@${version}`, 'version', '--json']);
|
|
43
180
|
return result.status === 0 && result.stdout.replace(/["\s]/gu, '') === version;
|
|
44
181
|
}
|
|
45
|
-
|
|
182
|
+
/**
|
|
183
|
+
* Polls the registry until it serves one version or the wait ends.
|
|
184
|
+
*
|
|
185
|
+
* @param name - The package name.
|
|
186
|
+
* @param version - The version.
|
|
187
|
+
* @param waitSeconds - How long to keep polling; 0 reads once.
|
|
188
|
+
* @param started - The millisecond the polling began. Default: now.
|
|
189
|
+
* @returns True if the registry served the version within the wait; false otherwise.
|
|
190
|
+
*/
|
|
191
|
+
export async function confirmServed(name, version, waitSeconds, started = Date.now()) {
|
|
46
192
|
const served = readServed(name, version);
|
|
47
193
|
if (served || Date.now() - started >= waitSeconds * 1000)
|
|
48
194
|
return served;
|
|
49
195
|
await waitFor(POLL_MS);
|
|
50
196
|
return confirmServed(name, version, waitSeconds, started);
|
|
51
197
|
}
|
|
52
|
-
|
|
198
|
+
/**
|
|
199
|
+
* Finds the nearest directory at or above one that holds a `.git` entry.
|
|
200
|
+
*
|
|
201
|
+
* @param directory - The directory to start from.
|
|
202
|
+
* @returns The nearest directory with a `.git` entry, or the filesystem root when none has one.
|
|
203
|
+
*/
|
|
204
|
+
export function findGitRoot(directory) {
|
|
53
205
|
return existsSync(join(directory, '.git')) || dirname(directory) === directory
|
|
54
206
|
? directory
|
|
55
207
|
: findGitRoot(dirname(directory));
|
|
56
208
|
}
|
|
57
|
-
|
|
209
|
+
/**
|
|
210
|
+
* Reads the error code npm printed.
|
|
211
|
+
*
|
|
212
|
+
* @param text - npm's standard error.
|
|
213
|
+
* @returns The first `E` code in the text, such as `EOTP` or `E401`, or undefined when none appears.
|
|
214
|
+
*/
|
|
215
|
+
export function readErrorCode(text) {
|
|
58
216
|
return text.match(/\b(E[A-Z0-9]{3,}|EOTP|E401|E403|E404)\b/u)?.[1];
|
|
59
217
|
}
|
|
60
|
-
|
|
218
|
+
/**
|
|
219
|
+
* Reads the name and version a directory's package manifest declares.
|
|
220
|
+
*
|
|
221
|
+
* @param directory - The directory that holds `package.json`.
|
|
222
|
+
* @returns The name and version, each undefined when the manifest is absent, unreadable, or lacks it.
|
|
223
|
+
*/
|
|
224
|
+
export function readManifestName(directory) {
|
|
61
225
|
const path = join(directory, 'package.json');
|
|
62
226
|
if (!existsSync(path))
|
|
63
227
|
return { name: undefined, version: undefined };
|
|
@@ -69,7 +233,15 @@ function readManifestName(directory) {
|
|
|
69
233
|
return { name: undefined, version: undefined };
|
|
70
234
|
}
|
|
71
235
|
}
|
|
72
|
-
|
|
236
|
+
/**
|
|
237
|
+
* Publishes one package directory and journals the upload.
|
|
238
|
+
*
|
|
239
|
+
* @param directory - The package directory.
|
|
240
|
+
* @param otp - The account's one-time code.
|
|
241
|
+
* @returns The upload: accepted when npm exited 0 and printed the acceptance line, else refused with
|
|
242
|
+
* the error code npm named.
|
|
243
|
+
*/
|
|
244
|
+
export function publishPackage(directory, otp) {
|
|
73
245
|
const manifest = readManifestName(directory);
|
|
74
246
|
const journal = `tmp/units/publish-${(manifest.name ?? directory).replace(/[^A-Za-z0-9.-]+/gu, '-')}.log`;
|
|
75
247
|
// The refusal code must survive an inherited silent npm log level.
|
|
@@ -97,7 +269,16 @@ function publishPackage(directory, otp) {
|
|
|
97
269
|
}
|
|
98
270
|
return upload;
|
|
99
271
|
}
|
|
100
|
-
|
|
272
|
+
/**
|
|
273
|
+
* Publishes a batch back to back and confirms each accepted version.
|
|
274
|
+
*
|
|
275
|
+
* @param directories - The package directories, in publish order.
|
|
276
|
+
* @param otp - The account's one-time code.
|
|
277
|
+
* @param waitSeconds - How long to wait for the registry to serve each accepted version.
|
|
278
|
+
* @returns One upload per directory published, ending at the first refusal; a directory after it is
|
|
279
|
+
* not published.
|
|
280
|
+
*/
|
|
281
|
+
export async function publishAll(directories, otp, waitSeconds) {
|
|
101
282
|
mkdirSync('tmp/units', { recursive: true });
|
|
102
283
|
// A step after the first refusal returns the state unchanged, so nothing publishes past it.
|
|
103
284
|
const { uploads } = directories.reduce((state, directory) => {
|
|
@@ -119,7 +300,18 @@ async function publishAll(directories, otp, waitSeconds) {
|
|
|
119
300
|
}
|
|
120
301
|
return confirmed;
|
|
121
302
|
}
|
|
122
|
-
|
|
303
|
+
/**
|
|
304
|
+
* Runs the mode the arguments name.
|
|
305
|
+
*
|
|
306
|
+
* @param argv - The arguments after the script path.
|
|
307
|
+
* @returns The exit code: 0 when the mode succeeded, 3 when it did not, 64 on usage.
|
|
308
|
+
*/
|
|
309
|
+
export async function main(argv) {
|
|
310
|
+
const unknown = readUnknownFlags(argv, FLAGS);
|
|
311
|
+
if (unknown.length > 0) {
|
|
312
|
+
console.error(`window: unknown flag ${unknown.join(', ')}; give each flag and its value as separate arguments\n${USAGE}`);
|
|
313
|
+
return 64;
|
|
314
|
+
}
|
|
123
315
|
const missing = readMissingFlags(argv, ['--wait', '--otp']);
|
|
124
316
|
if (missing.length > 0) {
|
|
125
317
|
console.error(`window: ${missing.join(', ')} given with no value`);
|
|
@@ -199,20 +391,22 @@ async function main(argv) {
|
|
|
199
391
|
console.error('usage: window.ts --confirm NAME@VERSION... [--wait SECONDS]');
|
|
200
392
|
return 64;
|
|
201
393
|
}
|
|
202
|
-
const
|
|
394
|
+
const results = [];
|
|
203
395
|
for (const target of targets) {
|
|
204
396
|
const at = target.lastIndexOf('@');
|
|
205
|
-
|
|
397
|
+
results.push({
|
|
206
398
|
target,
|
|
207
399
|
served: await confirmServed(target.slice(0, at), target.slice(at + 1), wait),
|
|
208
400
|
});
|
|
209
401
|
}
|
|
210
|
-
console.log(JSON.stringify({ mode: 'confirm',
|
|
211
|
-
return
|
|
402
|
+
console.log(JSON.stringify({ mode: 'confirm', results }));
|
|
403
|
+
return results.every((result) => result.served) ? 0 : 3;
|
|
212
404
|
}
|
|
213
|
-
console.error(
|
|
405
|
+
console.error(USAGE);
|
|
214
406
|
return 64;
|
|
215
407
|
}
|
|
216
|
-
|
|
217
|
-
process.
|
|
218
|
-
|
|
408
|
+
if (process.argv[1] !== undefined && realpathSync(process.argv[1]) === import.meta.filename) {
|
|
409
|
+
main(process.argv.slice(2)).then((code) => {
|
|
410
|
+
process.exitCode = code;
|
|
411
|
+
});
|
|
412
|
+
}
|