@guiho/runx 0.2.6 → 0.4.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/CHANGELOG.md +44 -0
- package/DOCS.md +128 -109
- package/README.md +58 -58
- package/devops/build-binaries.ts +44 -62
- package/devops/devops.xdocs.md +8 -5
- package/devops/install.ps1 +182 -152
- package/devops/install.sh +197 -262
- package/devops/installers.spec.ts +31 -0
- package/devops/verify-release-assets.ts +17 -0
- package/docs/decisions/decisions.xdocs.md +4 -0
- package/docs/decisions/interactive-init-manifest.md +187 -0
- package/docs/docs.xdocs.md +3 -1
- package/docs/plans/interactive-init-manifest.md +177 -0
- package/docs/plans/plans.xdocs.md +11 -0
- package/docs/plans/rfc-0034-cli-compliance-migration.md +586 -0
- package/docs/plans/upgrade-reliability-implementation.md +95 -0
- package/docs/reviews/implementation/implementation.xdocs.md +6 -0
- package/docs/reviews/implementation/interactive-init-manifest-review.md +69 -0
- package/docs/reviews/implementation/rfc-0034-cli-compliance-migration-review.md +59 -0
- package/docs/reviews/plans/interactive-init-manifest-review.md +82 -0
- package/docs/reviews/plans/plans.xdocs.md +10 -0
- package/docs/reviews/plans/rfc-0034-cli-compliance-migration-review.md +80 -0
- package/docs/reviews/plans/upgrade-reliability-implementation-review.md +65 -0
- package/docs/superpowers/specs/2026-07-15-upgrade-reliability-design.md +662 -0
- package/docs/superpowers/specs/specs.xdocs.md +24 -0
- package/docs/superpowers/superpowers.xdocs.md +21 -0
- package/docs/todo/rfc-0034-cli-compliance-migration-implementation.md +58 -0
- package/docs/todo/rfc-0034-cli-compliance-migration.md +151 -0
- package/docs/todo/todo.xdocs.md +6 -2
- package/docs/validation/interactive-init-manifest.md +79 -0
- package/docs/validation/rfc-0034-cli-compliance-migration.md +67 -0
- package/docs/validation/upgrade-reliability.md +124 -0
- package/docs/validation/validation.xdocs.md +9 -0
- package/library/agents.d.ts +28 -4
- package/library/agents.d.ts.map +1 -1
- package/library/agents.js +143 -41
- package/library/cli.d.ts.map +1 -1
- package/library/cli.js +297 -317
- package/library/configuration.d.ts +57 -0
- package/library/configuration.d.ts.map +1 -0
- package/library/configuration.js +111 -0
- package/library/embedded-resources.d.ts +6 -1
- package/library/embedded-resources.d.ts.map +1 -1
- package/library/embedded-resources.js +10 -4
- package/library/executor.d.ts +5 -1
- package/library/executor.d.ts.map +1 -1
- package/library/executor.js +10 -10
- package/library/help.d.ts +8 -4
- package/library/help.d.ts.map +1 -1
- package/library/help.js +70 -42
- package/library/init.d.ts +18 -0
- package/library/init.d.ts.map +1 -0
- package/library/init.js +43 -0
- package/library/manifest.d.ts +4 -40
- package/library/manifest.d.ts.map +1 -1
- package/library/manifest.js +4 -112
- package/library/path-utils.d.ts +13 -0
- package/library/path-utils.d.ts.map +1 -0
- package/library/path-utils.js +82 -0
- package/library/recovery.d.ts +7 -0
- package/library/recovery.d.ts.map +1 -0
- package/library/recovery.js +23 -0
- package/library/release-catalog.d.ts +32 -0
- package/library/release-catalog.d.ts.map +1 -0
- package/library/release-catalog.js +124 -0
- package/library/self-management.d.ts +24 -4
- package/library/self-management.d.ts.map +1 -1
- package/library/self-management.js +279 -99
- package/library/storage.d.ts +13 -0
- package/library/storage.d.ts.map +1 -0
- package/library/storage.js +38 -0
- package/library/types.d.ts +11 -16
- package/library/types.d.ts.map +1 -1
- package/library/types.js +3 -0
- package/library/update-cache.d.ts +21 -0
- package/library/update-cache.d.ts.map +1 -0
- package/library/update-cache.js +68 -0
- package/library/upgrade-reporting.d.ts +11 -0
- package/library/upgrade-reporting.d.ts.map +1 -0
- package/library/upgrade-reporting.js +67 -0
- package/library/upgrade-types.d.ts +72 -0
- package/library/upgrade-types.d.ts.map +1 -0
- package/library/upgrade-types.js +3 -0
- package/package.json +6 -3
- package/scripts/runx-bin.mjs +49 -0
- package/scripts/runx-bin.spec.ts +62 -0
- package/scripts/scripts.xdocs.md +3 -3
- package/skills/guiho-s-runx/SKILL.md +64 -59
- package/skills/guiho-s-runx/guiho-s-runx.xdocs.md +7 -4
- package/skills/skills.xdocs.md +1 -1
- package/docs/todo/implement-runx-alpha.md +0 -36
- package/scripts/runx-bin.ts +0 -24
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade-reporting.d.ts","sourceRoot":"","sources":["../source/upgrade-reporting.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAwB,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAE1H,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,GACpB,CAAA;AAED,QAAA,MAAM,oBAAoB,QAAO,MAId,CAAA;AAEnB,QAAA,MAAM,iBAAiB,SAAU,WAAW,KAAG,MAS5B,CAAA;AAEnB,QAAA,MAAM,kBAAkB,UAAW,YAAY,KAAG,MAWjD,CAAA;AAED,QAAA,MAAM,mBAAmB,WAAY,eAAe,KAAG,MAWtD,CAAA;AAYD,QAAA,MAAM,oBAAoB,YAAa,cAAc,KAAG,MAavD,CAAA"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright © 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
export { renderReleaseCatalog, renderUpgradeEvent, renderUpgradeHeading, renderUpgradePlan, renderUpgradeResult, };
|
|
5
|
+
const renderUpgradeHeading = () => [
|
|
6
|
+
'------------------------------------------------------------',
|
|
7
|
+
' Upgrading the CLI',
|
|
8
|
+
'------------------------------------------------------------',
|
|
9
|
+
].join('\n') + '\n';
|
|
10
|
+
const renderUpgradePlan = (plan) => [
|
|
11
|
+
` current : ${plan.currentVersion}`,
|
|
12
|
+
` target : ${plan.targetVersion}`,
|
|
13
|
+
` os : ${plan.os}`,
|
|
14
|
+
` arch : ${plan.arch}`,
|
|
15
|
+
` binary : ${plan.assetName}`,
|
|
16
|
+
` path : ${plan.executablePath.replaceAll('\\', '/')}`,
|
|
17
|
+
` url : ${plan.assetUrl}`,
|
|
18
|
+
'------------------------------------------------------------',
|
|
19
|
+
].join('\n') + '\n';
|
|
20
|
+
const renderUpgradeEvent = (event) => {
|
|
21
|
+
if (event.status !== 'started' || event.phase === 'plan')
|
|
22
|
+
return '';
|
|
23
|
+
const labels = {
|
|
24
|
+
download: 'Downloading...',
|
|
25
|
+
validate: 'Validating...',
|
|
26
|
+
replace: 'Replacing...',
|
|
27
|
+
verify: 'Verifying...',
|
|
28
|
+
cleanup: 'Cleaning up...',
|
|
29
|
+
};
|
|
30
|
+
const label = labels[event.phase];
|
|
31
|
+
return label ? `${label}\n` : '';
|
|
32
|
+
};
|
|
33
|
+
const renderUpgradeResult = (result) => {
|
|
34
|
+
const summary = result.outcome === 'upgraded'
|
|
35
|
+
? `Upgrade complete: ${result.plan?.currentVersion} -> ${result.plan?.targetVersion}`
|
|
36
|
+
: result.outcome === 'up-to-date'
|
|
37
|
+
? `Already up to date: ${result.result?.installedVersion ?? result.recovery.targetVersion}`
|
|
38
|
+
: result.outcome === 'dry-run'
|
|
39
|
+
? `Dry run complete: ${result.plan?.currentVersion} -> ${result.plan?.targetVersion}`
|
|
40
|
+
: result.outcome === 'rolled-back'
|
|
41
|
+
? `Upgrade failed during ${result.error?.phase ?? 'replace'}; restored RunX ${result.result?.installedVersion ?? result.recovery.targetVersion}.`
|
|
42
|
+
: `Upgrade failed during ${result.error?.phase ?? 'plan'}.`;
|
|
43
|
+
return `${summary}\n\n${renderRecovery(result.recovery, result.outcome === 'failed' || result.outcome === 'rolled-back')}\n`;
|
|
44
|
+
};
|
|
45
|
+
const renderRecovery = (recovery, repair) => [
|
|
46
|
+
recovery.targetSource === 'fallback-current'
|
|
47
|
+
? `Repair reinstall (target lookup failed; pinned to installed RunX ${recovery.targetVersion}):`
|
|
48
|
+
: `${repair ? 'To repair RunX' : 'If the new version is not active'}, install RunX ${recovery.targetVersion} directly:`,
|
|
49
|
+
` ${recovery.installCommand}`,
|
|
50
|
+
'',
|
|
51
|
+
'If RunX is still running and blocks installation, stop it first:',
|
|
52
|
+
` ${recovery.stopProcessCommand}`,
|
|
53
|
+
].join('\n');
|
|
54
|
+
const renderReleaseCatalog = (catalog) => {
|
|
55
|
+
const headers = ['VERSION', 'CHANNEL', 'PUBLISHED', 'CURRENT', 'LATEST', 'ASSET'];
|
|
56
|
+
const rows = catalog.releases.map((release) => [
|
|
57
|
+
release.version,
|
|
58
|
+
release.channel,
|
|
59
|
+
release.publishedAt?.slice(0, 10) ?? '-',
|
|
60
|
+
release.current ? 'yes' : '',
|
|
61
|
+
release.latestStable ? 'yes' : '',
|
|
62
|
+
release.compatibleAsset ? 'yes' : 'no',
|
|
63
|
+
]);
|
|
64
|
+
const widths = headers.map((header, index) => Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0)));
|
|
65
|
+
const line = (values) => values.map((value, index) => value.padEnd(widths[index] ?? value.length)).join(' ').trimEnd();
|
|
66
|
+
return ['AVAILABLE RUNX VERSIONS', '', line(headers), ...rows.map(line)].join('\n') + '\n';
|
|
67
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright © 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
export type UpgradeOs = 'windows' | 'darwin' | 'linux';
|
|
5
|
+
export type UpgradeArch = 'x64' | 'arm64';
|
|
6
|
+
export type UpgradeVariant = 'baseline' | 'default' | 'modern';
|
|
7
|
+
export type ReleaseAsset = {
|
|
8
|
+
name: string;
|
|
9
|
+
url: string;
|
|
10
|
+
};
|
|
11
|
+
export type ReleaseCatalogEntry = {
|
|
12
|
+
tag: string;
|
|
13
|
+
version: string;
|
|
14
|
+
channel: string;
|
|
15
|
+
prerelease: boolean;
|
|
16
|
+
publishedAt: string | null;
|
|
17
|
+
current: boolean;
|
|
18
|
+
latestStable: boolean;
|
|
19
|
+
compatibleAsset: ReleaseAsset | null;
|
|
20
|
+
};
|
|
21
|
+
export type ReleaseCatalog = {
|
|
22
|
+
schemaVersion: 1;
|
|
23
|
+
command: 'runx upgrade list';
|
|
24
|
+
currentVersion: string;
|
|
25
|
+
latestStableVersion: string | null;
|
|
26
|
+
releases: ReleaseCatalogEntry[];
|
|
27
|
+
};
|
|
28
|
+
export type RecoveryInstructions = {
|
|
29
|
+
targetVersion: string;
|
|
30
|
+
targetSource: 'resolved' | 'fallback-current';
|
|
31
|
+
installCommand: string;
|
|
32
|
+
stopProcessCommand: string;
|
|
33
|
+
};
|
|
34
|
+
export type UpgradePlan = {
|
|
35
|
+
currentVersion: string;
|
|
36
|
+
targetVersion: string;
|
|
37
|
+
os: UpgradeOs;
|
|
38
|
+
arch: UpgradeArch;
|
|
39
|
+
assetName: string;
|
|
40
|
+
assetUrl: string;
|
|
41
|
+
executablePath: string;
|
|
42
|
+
};
|
|
43
|
+
export type UpgradePhase = 'plan' | 'download' | 'validate' | 'replace' | 'verify' | 'cache' | 'cleanup';
|
|
44
|
+
export type UpgradePhaseStatus = 'started' | 'succeeded' | 'skipped' | 'failed';
|
|
45
|
+
export type UpgradeEvent = {
|
|
46
|
+
sequence: number;
|
|
47
|
+
phase: UpgradePhase;
|
|
48
|
+
status: UpgradePhaseStatus;
|
|
49
|
+
message?: string;
|
|
50
|
+
};
|
|
51
|
+
export type UpgradeOutcome = 'upgraded' | 'up-to-date' | 'dry-run' | 'rolled-back' | 'failed';
|
|
52
|
+
export type UpgradeResult = {
|
|
53
|
+
installedVersion: string;
|
|
54
|
+
cleanupDeferred: boolean;
|
|
55
|
+
};
|
|
56
|
+
export type UpgradeErrorCode = 'release_lookup_failed' | 'release_payload_invalid' | 'no_compatible_asset' | 'download_failed' | 'download_invalid' | 'backup_failed' | 'replace_failed' | 'verification_failed' | 'rollback_failed' | 'installer_verification_failed';
|
|
57
|
+
export type UpgradeError = {
|
|
58
|
+
code: UpgradeErrorCode;
|
|
59
|
+
phase: UpgradePhase;
|
|
60
|
+
message: string;
|
|
61
|
+
};
|
|
62
|
+
export type UpgradeEnvelope = {
|
|
63
|
+
schemaVersion: 1;
|
|
64
|
+
command: 'runx upgrade';
|
|
65
|
+
outcome: UpgradeOutcome;
|
|
66
|
+
plan: UpgradePlan | null;
|
|
67
|
+
events: UpgradeEvent[];
|
|
68
|
+
result: UpgradeResult | null;
|
|
69
|
+
recovery: RecoveryInstructions;
|
|
70
|
+
error: UpgradeError | null;
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=upgrade-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade-types.d.ts","sourceRoot":"","sources":["../source/upgrade-types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guiho/runx",
|
|
3
3
|
"description": "A language-agnostic, documented command catalog and local CLI executor.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./library/guiho-runx.js",
|
|
7
7
|
"types": "./library/guiho-runx.d.ts",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"bin": {
|
|
15
|
-
"runx": "scripts/runx-bin.
|
|
15
|
+
"runx": "scripts/runx-bin.mjs"
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"library/",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"build": "rm -rf library && tsc -p .",
|
|
58
58
|
"binary": "bun build source/guiho-runx-native-bin.ts --compile --outfile bin/runx",
|
|
59
59
|
"binaries": "bun run devops/build-binaries.ts",
|
|
60
|
+
"verify-assets": "bun run devops/verify-release-assets.ts",
|
|
60
61
|
"test": "bun test",
|
|
61
62
|
"typecheck": "tsc -p . --noEmit",
|
|
62
63
|
"check": "bun run typecheck && bun test",
|
|
@@ -69,10 +70,12 @@
|
|
|
69
70
|
},
|
|
70
71
|
"dependencies": {
|
|
71
72
|
"@sinclair/typebox": "^0.34.52",
|
|
72
|
-
"citty": "^0.2.2"
|
|
73
|
+
"citty": "^0.2.2",
|
|
74
|
+
"semver": "^7.8.5"
|
|
73
75
|
},
|
|
74
76
|
"devDependencies": {
|
|
75
77
|
"@types/bun": "^1.3.14",
|
|
78
|
+
"@types/semver": "^7.7.1",
|
|
76
79
|
"typescript": "^7.0.2"
|
|
77
80
|
}
|
|
78
81
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @copyright Copyright © 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { spawn } from 'node:child_process'
|
|
8
|
+
import { chmod, mkdir, rename, rm, stat, writeFile } from 'node:fs/promises'
|
|
9
|
+
import { arch, homedir, platform } from 'node:os'
|
|
10
|
+
import { join } from 'node:path'
|
|
11
|
+
|
|
12
|
+
import packageJson from '../package.json' with { type: 'json' }
|
|
13
|
+
|
|
14
|
+
const os = platform() === 'win32' ? 'windows' : platform() === 'darwin' ? 'darwin' : platform() === 'linux' ? 'linux' : null
|
|
15
|
+
const cpu = arch() === 'x64' ? 'x64' : arch() === 'arm64' ? 'arm64' : null
|
|
16
|
+
if (!os || !cpu) fail(`Unsupported platform: ${platform()} ${arch()}`)
|
|
17
|
+
|
|
18
|
+
const suffix = os === 'windows' ? '.exe' : ''
|
|
19
|
+
const asset = cpu === 'arm64' ? `runx-${os}-arm64${suffix}` : `runx-${os}-x64-baseline${suffix}`
|
|
20
|
+
const cache = process.env.RUNX_NATIVE_CACHE || join(homedir(), '.guiho', 'runx', 'npm', packageJson.version)
|
|
21
|
+
const executable = join(cache, `runx${suffix}`)
|
|
22
|
+
const tag = encodeURIComponent(`@guiho/runx@${packageJson.version}`)
|
|
23
|
+
const downloadBase = (process.env.RUNX_DOWNLOAD_BASE_URL || 'https://github.com/CGuiho/runx/releases/download').replace(/\/$/, '')
|
|
24
|
+
const url = `${downloadBase}/${tag}/${asset}`
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
await stat(executable)
|
|
28
|
+
} catch {
|
|
29
|
+
await mkdir(cache, { recursive: true })
|
|
30
|
+
const response = await fetch(url, { redirect: 'follow' })
|
|
31
|
+
if (!response.ok) fail(`Could not download ${asset}: HTTP ${response.status}`)
|
|
32
|
+
const temporary = `${executable}.${process.pid}.tmp`
|
|
33
|
+
await writeFile(temporary, new Uint8Array(await response.arrayBuffer()), { flag: 'wx' })
|
|
34
|
+
if (os !== 'windows') await chmod(temporary, 0o755)
|
|
35
|
+
await rename(temporary, executable)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const child = spawn(executable, process.argv.slice(2), { env: process.env, stdio: 'inherit' })
|
|
39
|
+
child.once('error', (error) => fail(error.message))
|
|
40
|
+
child.once('exit', (code, signal) => {
|
|
41
|
+
if (signal) process.kill(process.pid, signal)
|
|
42
|
+
else process.exit(code ?? 1)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
function fail(message) {
|
|
46
|
+
process.stderr.write(`error: ${message}\n`)
|
|
47
|
+
void rm(executable, { force: true }).catch(() => undefined)
|
|
48
|
+
process.exit(1)
|
|
49
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright © 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { afterEach, expect, test } from 'bun:test'
|
|
6
|
+
import { mkdtemp, rm } from 'node:fs/promises'
|
|
7
|
+
import { tmpdir } from 'node:os'
|
|
8
|
+
import { join } from 'node:path'
|
|
9
|
+
|
|
10
|
+
let directory = ''
|
|
11
|
+
|
|
12
|
+
afterEach(async () => {
|
|
13
|
+
if (directory) await rm(directory, { recursive: true, force: true })
|
|
14
|
+
directory = ''
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
test('packed npm bootstrap downloads and delegates with Node while Bun is absent from PATH', async () => {
|
|
18
|
+
const node = Bun.which('node')
|
|
19
|
+
if (!node) throw new Error('Node is required for the npm bootstrap test.')
|
|
20
|
+
directory = await mkdtemp(join(tmpdir(), 'runx-npm-'))
|
|
21
|
+
const root = Bun.fileURLToPath(new URL('..', import.meta.url))
|
|
22
|
+
const packed = Bun.spawn([process.execPath, 'pm', 'pack', '--destination', directory, '--ignore-scripts'], {
|
|
23
|
+
cwd: root,
|
|
24
|
+
stdout: 'pipe',
|
|
25
|
+
stderr: 'pipe',
|
|
26
|
+
})
|
|
27
|
+
const [packCode, packOutput, packError] = await Promise.all([
|
|
28
|
+
packed.exited,
|
|
29
|
+
new Response(packed.stdout).text(),
|
|
30
|
+
new Response(packed.stderr).text(),
|
|
31
|
+
])
|
|
32
|
+
expect(packCode, packError).toBe(0)
|
|
33
|
+
const archiveName = [...new Bun.Glob('*.tgz').scanSync({ cwd: directory, onlyFiles: true })][0]
|
|
34
|
+
expect(archiveName, packOutput).toBeDefined()
|
|
35
|
+
const extraction = Bun.spawn(['tar', '-xzf', join(directory, archiveName), '-C', directory])
|
|
36
|
+
expect(await extraction.exited).toBe(0)
|
|
37
|
+
|
|
38
|
+
const server = Bun.serve({ port: 0, fetch: () => new Response(Bun.file(process.execPath)) })
|
|
39
|
+
try {
|
|
40
|
+
const wrapper = join(directory, 'package', 'scripts', 'runx-bin.mjs')
|
|
41
|
+
const child = Bun.spawn([node, wrapper, '--version'], {
|
|
42
|
+
cwd: join(directory, 'package'),
|
|
43
|
+
env: {
|
|
44
|
+
...process.env,
|
|
45
|
+
PATH: join(node, '..'),
|
|
46
|
+
RUNX_NATIVE_CACHE: join(directory, 'native-cache'),
|
|
47
|
+
RUNX_DOWNLOAD_BASE_URL: `http://127.0.0.1:${server.port}`,
|
|
48
|
+
},
|
|
49
|
+
stdout: 'pipe',
|
|
50
|
+
stderr: 'pipe',
|
|
51
|
+
})
|
|
52
|
+
const [exitCode, stdout, stderr] = await Promise.all([
|
|
53
|
+
child.exited,
|
|
54
|
+
new Response(child.stdout).text(),
|
|
55
|
+
new Response(child.stderr).text(),
|
|
56
|
+
])
|
|
57
|
+
expect(exitCode, stderr).toBe(0)
|
|
58
|
+
expect(stdout.trim()).toBe(process.versions.bun)
|
|
59
|
+
} finally {
|
|
60
|
+
server.stop(true)
|
|
61
|
+
}
|
|
62
|
+
})
|
package/scripts/scripts.xdocs.md
CHANGED
|
@@ -4,7 +4,8 @@ description: Package-manager launcher scripts for RunX.
|
|
|
4
4
|
parent: runx
|
|
5
5
|
children: []
|
|
6
6
|
files:
|
|
7
|
-
runx-bin.
|
|
7
|
+
runx-bin.mjs: Node-compatible npm bootstrap that downloads, caches, and delegates to the exact native release binary.
|
|
8
|
+
runx-bin.spec.ts: Packs the npm package and proves Node-only bootstrap download/delegation with Bun absent from PATH.
|
|
8
9
|
documents: {}
|
|
9
10
|
tags:
|
|
10
11
|
- scripts
|
|
@@ -16,5 +17,4 @@ flags: []
|
|
|
16
17
|
status: stable
|
|
17
18
|
---
|
|
18
19
|
|
|
19
|
-
The
|
|
20
|
-
and development checkouts without requiring unpublished source files.
|
|
20
|
+
The npm launcher contains no RunX domain logic and requires no Bun installation.
|
|
@@ -1,73 +1,78 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: guiho-s-runx
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
created: 2026-07-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
description: Use when inspecting, validating, documenting, or safely executing a RunX runx.yaml command catalog.
|
|
4
|
+
purpose: Teach agents the supported RunX catalog inspection and execution workflow.
|
|
5
|
+
created: 2026-07-18
|
|
6
|
+
flags:
|
|
7
|
+
- bundled
|
|
8
8
|
tags:
|
|
9
|
-
- agents
|
|
10
9
|
- runx
|
|
10
|
+
- cli
|
|
11
11
|
keywords:
|
|
12
|
-
- runx
|
|
13
|
-
- citty
|
|
12
|
+
- runx.yaml
|
|
14
13
|
- command catalog
|
|
15
14
|
- dry run
|
|
15
|
+
owner: guiho-s-runx
|
|
16
|
+
metadata:
|
|
17
|
+
version: "0.2.0"
|
|
16
18
|
---
|
|
17
19
|
|
|
18
20
|
# GUIHO RunX
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
- `runx
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- Use `runx <command> --help` for command-specific Citty usage. `runx -h` and
|
|
46
|
-
`runx -v` are global operations and do not require a manifest.
|
|
47
|
-
|
|
48
|
-
## Maintain Manifests
|
|
49
|
-
|
|
50
|
-
- Keep `uid`, `id`, `group`, `summary`, `description`, and `command` present.
|
|
51
|
-
- Keep UIDs stable; never reuse a UID for a materially different command.
|
|
52
|
-
- Use a group for organization, a concise summary for listings, and a complete
|
|
53
|
-
description for prerequisites, effects, and risk.
|
|
54
|
-
- Set `confirm: always` for destructive, release, deployment, migration, and
|
|
55
|
-
production-impacting commands when confirmation is useful.
|
|
56
|
-
- Run `runx check` after every manifest change. It rejects unknown fields,
|
|
57
|
-
duplicate UIDs/selectors, missing descriptions, invalid working directories,
|
|
58
|
-
and unsupported shell choices.
|
|
59
|
-
|
|
60
|
-
## Useful Commands
|
|
22
|
+
## Inspect Before Execution
|
|
23
|
+
|
|
24
|
+
1. Run `runx check --format json`.
|
|
25
|
+
2. Run `runx list --format json`.
|
|
26
|
+
3. Prefer a stable UID for automation.
|
|
27
|
+
4. Run `runx describe <uid>` before unfamiliar work.
|
|
28
|
+
5. Run `runx run <uid> --dry-run` before any mutation or high-impact command.
|
|
29
|
+
|
|
30
|
+
RunX manifests are trusted executable code. A group name is not a safety
|
|
31
|
+
boundary. Never add `--yes` unless the developer explicitly authorizes the
|
|
32
|
+
specific confirmation-gated command.
|
|
33
|
+
|
|
34
|
+
## Configuration
|
|
35
|
+
|
|
36
|
+
RunX resolves YAML only:
|
|
37
|
+
|
|
38
|
+
1. `--config <path>`;
|
|
39
|
+
2. effective-cwd `runx.yaml`;
|
|
40
|
+
3. `~/.guiho/runx/runx.yaml`.
|
|
41
|
+
|
|
42
|
+
It does not search parent directories.
|
|
43
|
+
|
|
44
|
+
## Execute
|
|
45
|
+
|
|
46
|
+
Use only:
|
|
61
47
|
|
|
62
48
|
```text
|
|
63
|
-
runx
|
|
64
|
-
runx -h Show generated command help.
|
|
65
|
-
runx -v Show the installed version.
|
|
66
|
-
runx list List the nearest manifest.
|
|
67
|
-
runx describe <uid> Explain one command without execution.
|
|
68
|
-
runx run <uid> --dry-run Inspect the execution plan.
|
|
69
|
-
runx r <uid> Run through the short alias.
|
|
70
|
-
runx agents install local Install this skill into .agents/skills.
|
|
71
|
-
runx --help-tree Show the command hierarchy.
|
|
72
|
-
runx --help-docs Show manifest documentation guidance.
|
|
49
|
+
runx run <uid>
|
|
73
50
|
```
|
|
51
|
+
|
|
52
|
+
Listing, describing, checking, help, agent operations, and dry runs must never
|
|
53
|
+
execute a manifest command. Preserve the child command's exact exit code.
|
|
54
|
+
|
|
55
|
+
## Maintain Catalogs
|
|
56
|
+
|
|
57
|
+
- Keep `uid`, `id`, `group`, `summary`, `description`, and `command`.
|
|
58
|
+
- Keep UIDs stable and never reuse one for materially different behavior.
|
|
59
|
+
- Use `confirm: always` for destructive, release, deployment, migration, and
|
|
60
|
+
production-impacting operations.
|
|
61
|
+
- Do not place secrets in `runx.yaml`.
|
|
62
|
+
- Run `runx check` after every change.
|
|
63
|
+
|
|
64
|
+
## Agent And Upgrade Commands
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
runx agent skill list
|
|
68
|
+
runx agent skill show guiho-s-runx
|
|
69
|
+
runx agent instruction show
|
|
70
|
+
runx agent prompt list --names
|
|
71
|
+
runx agent prompt show guiho-i-runx
|
|
72
|
+
runx upgrade check
|
|
73
|
+
runx upgrade list
|
|
74
|
+
runx upgrade --dry-run
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Use `--help`, `--help-tree`, or `--help-docs` at any command scope for the
|
|
78
|
+
current executable contract.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
subject: guiho-s-runx
|
|
3
|
-
description: Agent workflow for
|
|
3
|
+
description: Agent workflow for safe RunX catalog execution and verified native upgrade/list/recovery operations.
|
|
4
4
|
parent: runx-skills
|
|
5
5
|
children: []
|
|
6
6
|
files:
|
|
7
|
-
SKILL.md:
|
|
7
|
+
SKILL.md: RFC-aligned RunX catalog inspection, execution safety, YAML precedence, agent, and upgrade guidance.
|
|
8
8
|
documents:
|
|
9
|
-
SKILL.md: RunX-specific
|
|
9
|
+
SKILL.md: RunX-specific command execution and verified native self-upgrade workflow.
|
|
10
10
|
tags:
|
|
11
11
|
- agents
|
|
12
12
|
- runx
|
|
@@ -15,9 +15,12 @@ keywords:
|
|
|
15
15
|
- citty
|
|
16
16
|
- command catalog
|
|
17
17
|
- dry run
|
|
18
|
+
- runx upgrade
|
|
19
|
+
- recovery install
|
|
18
20
|
flags: []
|
|
19
21
|
status: stable
|
|
20
22
|
---
|
|
21
23
|
|
|
22
24
|
The skill makes manifest inspection, UID selection, dry runs, and explicit
|
|
23
|
-
confirmation the default agent workflow for RunX commands
|
|
25
|
+
confirmation the default agent workflow for RunX commands and teaches agents
|
|
26
|
+
how to interpret transactional native upgrades and their recovery contract.
|
package/skills/skills.xdocs.md
CHANGED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Implement RunX Alpha Command Catalog
|
|
3
|
-
purpose: Define the expected outcome, constraints, and completion signals for task 1 in TODO.md.
|
|
4
|
-
description: Describes the first RunX CLI release and the safety, documentation, and validation constraints that govern it.
|
|
5
|
-
created: 2026-07-12
|
|
6
|
-
flags:
|
|
7
|
-
- implementation
|
|
8
|
-
tags:
|
|
9
|
-
- todo
|
|
10
|
-
- cli
|
|
11
|
-
keywords:
|
|
12
|
-
- runx
|
|
13
|
-
- alpha
|
|
14
|
-
owner: runx-todo
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
# Implement RunX Alpha Command Catalog
|
|
18
|
-
|
|
19
|
-
## Todo Index
|
|
20
|
-
|
|
21
|
-
- Task: `1. Implement RunX Alpha Command Catalog`
|
|
22
|
-
- Status: completed
|
|
23
|
-
- Index: [TODO.md](../../TODO.md)
|
|
24
|
-
|
|
25
|
-
## Outcome
|
|
26
|
-
|
|
27
|
-
Deliver a documented, locally executable RunX alpha that meets the approved
|
|
28
|
-
command-catalog acceptance criteria without publishing a package.
|
|
29
|
-
|
|
30
|
-
## Watch-outs
|
|
31
|
-
|
|
32
|
-
- Preserve read-only behavior for list, describe, check, and dry run paths.
|
|
33
|
-
- Never place secrets in a manifest or run confirmation-gated commands without
|
|
34
|
-
`--yes`.
|
|
35
|
-
- Keep every new module and document represented by XDocs metadata.
|
|
36
|
-
- Use Mirror for the version transition and keep commits one file at a time.
|
package/scripts/runx-bin.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
const args = process.argv.slice(2)
|
|
4
|
-
const binaryPath = new URL(`../vendor/runx${process.platform === 'win32' ? '.exe' : ''}`, import.meta.url)
|
|
5
|
-
const libraryPath = new URL('../library/guiho-runx-bin.js', import.meta.url)
|
|
6
|
-
const sourcePath = new URL('../source/guiho-runx-bin.ts', import.meta.url)
|
|
7
|
-
|
|
8
|
-
if (await Bun.file(binaryPath).exists()) {
|
|
9
|
-
const child = Bun.spawn([Bun.fileURLToPath(binaryPath), ...args], { stdin: 'inherit', stdout: 'inherit', stderr: 'inherit' })
|
|
10
|
-
process.exit(await child.exited)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
if (await Bun.file(libraryPath).exists()) {
|
|
14
|
-
const child = Bun.spawn([process.execPath, Bun.fileURLToPath(libraryPath), ...args], { stdin: 'inherit', stdout: 'inherit', stderr: 'inherit' })
|
|
15
|
-
process.exit(await child.exited)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (await Bun.file(sourcePath).exists()) {
|
|
19
|
-
const child = Bun.spawn([process.execPath, Bun.fileURLToPath(sourcePath), ...args], { stdin: 'inherit', stdout: 'inherit', stderr: 'inherit' })
|
|
20
|
-
process.exit(await child.exited)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
console.error('error: RunX executable is unavailable. Install an official native release or reinstall @guiho/runx.')
|
|
24
|
-
process.exit(1)
|