jorgex-stack 1.9.61 → 1.9.62

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.
@@ -0,0 +1,21 @@
1
+ interface ObservedPiCiArtifact {
2
+ version: string;
3
+ tarballUrl: string;
4
+ integrity: string;
5
+ bytes: number;
6
+ sha256: string;
7
+ sha512: string;
8
+ }
9
+ interface PrepareObservedPiCiArtifactInput {
10
+ tarballPath: string;
11
+ candidatePath: string;
12
+ fetchImpl: typeof fetch;
13
+ }
14
+ /**
15
+ * T06 CI observed artifact: resolve the live `dist-tags.latest` candidate,
16
+ * download the exact verified tarball, then freeze the observed identity as
17
+ * a bounded private JSON. Filesystem guards run before any network.
18
+ */
19
+ declare function prepareObservedPiCiArtifact(input: PrepareObservedPiCiArtifactInput): Promise<ObservedPiCiArtifact>;
20
+
21
+ export { type ObservedPiCiArtifact, type PrepareObservedPiCiArtifactInput, prepareObservedPiCiArtifact };
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ downloadVerifiedPiTarball,
4
+ resolveLatestPiRelease
5
+ } from "./chunk-KGL5VNVZ.js";
6
+
7
+ // src/lib/pi-ci-artifact.ts
8
+ import fs from "fs";
9
+ import path from "path";
10
+ import { randomBytes } from "crypto";
11
+ import { pathToFileURL } from "url";
12
+ var MAX_CANDIDATE_BYTES = 64 * 1024;
13
+ function fail(message) {
14
+ throw new Error(`pi-ci-artifact: ${message}`);
15
+ }
16
+ function lstatOrNull(p) {
17
+ try {
18
+ return fs.lstatSync(p);
19
+ } catch {
20
+ return null;
21
+ }
22
+ }
23
+ function assertAbsolute(label, value) {
24
+ if (typeof value !== "string" || value === "" || !path.isAbsolute(value)) {
25
+ fail(`${label} must be a non-empty absolute path`);
26
+ }
27
+ return path.resolve(value);
28
+ }
29
+ function assertParentRealDir(resolvedFile, label) {
30
+ const dir = path.dirname(resolvedFile);
31
+ const st = lstatOrNull(dir);
32
+ if (st === null || !st.isDirectory() || st.isSymbolicLink()) {
33
+ fail(`${label} parent must be a real directory: ${dir}`);
34
+ }
35
+ return dir;
36
+ }
37
+ async function prepareObservedPiCiArtifact(input) {
38
+ if (input === null || typeof input !== "object" || Array.isArray(input)) {
39
+ fail("input must be an object");
40
+ }
41
+ const { tarballPath, candidatePath, fetchImpl } = input;
42
+ if (typeof fetchImpl !== "function") {
43
+ fail("fetchImpl must be a function");
44
+ }
45
+ const tarballResolved = assertAbsolute("tarballPath", tarballPath);
46
+ const candidateResolved = assertAbsolute("candidatePath", candidatePath);
47
+ if (tarballResolved === candidateResolved) {
48
+ fail("tarballPath and candidatePath must differ");
49
+ }
50
+ const candidateDir = assertParentRealDir(candidateResolved, "candidatePath");
51
+ assertParentRealDir(tarballResolved, "tarballPath");
52
+ const candidateExisting = lstatOrNull(candidateResolved);
53
+ if (candidateExisting !== null) {
54
+ fail(`candidate already exists: ${candidateResolved}`);
55
+ }
56
+ const tarballExisting = lstatOrNull(tarballResolved);
57
+ if (tarballExisting !== null && tarballExisting.isSymbolicLink()) {
58
+ fail(`tarball path must not be a symlink: ${tarballResolved}`);
59
+ }
60
+ let release;
61
+ try {
62
+ release = await resolveLatestPiRelease(fetchImpl);
63
+ } catch (error) {
64
+ if (error instanceof Error && /^(pi-ci-artifact|pi-release-resolver): /.test(error.message)) {
65
+ throw error;
66
+ }
67
+ fail(`provider release resolution failed: ${error instanceof Error ? error.message : String(error)}`);
68
+ }
69
+ let artifact;
70
+ try {
71
+ artifact = await downloadVerifiedPiTarball(
72
+ release,
73
+ tarballResolved,
74
+ fetchImpl
75
+ );
76
+ } catch (error) {
77
+ if (error instanceof Error && /^(pi-ci-artifact|pi-release-resolver): /.test(error.message)) {
78
+ throw error;
79
+ }
80
+ fail(`verified tarball acquisition failed: ${error instanceof Error ? error.message : String(error)}`);
81
+ }
82
+ const payload = {
83
+ version: release.version,
84
+ tarballUrl: release.tarballUrl,
85
+ integrity: release.integrity,
86
+ bytes: artifact.bytes,
87
+ sha256: artifact.sha256,
88
+ sha512: artifact.sha512
89
+ };
90
+ const serialized = `${JSON.stringify(payload)}
91
+ `;
92
+ if (Buffer.byteLength(serialized, "utf8") >= MAX_CANDIDATE_BYTES) {
93
+ fail("candidate JSON exceeds 64 KiB");
94
+ }
95
+ const tempPath = path.join(
96
+ candidateDir,
97
+ `pi-ci-candidate-partial-${process.pid}-${randomBytes(8).toString("hex")}.json`
98
+ );
99
+ let fd;
100
+ try {
101
+ fd = fs.openSync(tempPath, "wx", 384);
102
+ } catch {
103
+ fail(`cannot stage candidate temp: ${tempPath}`);
104
+ }
105
+ let fdClosed = false;
106
+ const closeFd = () => {
107
+ if (fdClosed) return;
108
+ fdClosed = true;
109
+ try {
110
+ fs.closeSync(fd);
111
+ } catch {
112
+ }
113
+ };
114
+ const discardStaged = () => {
115
+ closeFd();
116
+ try {
117
+ fs.rmSync(tempPath, { force: true });
118
+ } catch {
119
+ }
120
+ };
121
+ try {
122
+ try {
123
+ fs.writeSync(fd, serialized, null, "utf8");
124
+ } catch {
125
+ fail("cannot write candidate temp");
126
+ }
127
+ closeFd();
128
+ try {
129
+ fs.chmodSync(tempPath, 384);
130
+ } catch {
131
+ fail("cannot secure candidate temp");
132
+ }
133
+ try {
134
+ fs.linkSync(tempPath, candidateResolved);
135
+ } catch {
136
+ fail(`candidate already exists: ${candidateResolved}`);
137
+ }
138
+ try {
139
+ fs.rmSync(tempPath, { force: true });
140
+ } catch {
141
+ }
142
+ } catch (error) {
143
+ discardStaged();
144
+ if (error instanceof Error && error.message.startsWith("pi-ci-artifact: ")) throw error;
145
+ fail(`candidate publish failed: ${error instanceof Error ? error.message : String(error)}`);
146
+ }
147
+ return payload;
148
+ }
149
+ if (process.argv[1] !== void 0 && import.meta.url === pathToFileURL(process.argv[1]).href) {
150
+ const args = process.argv.slice(2);
151
+ if (args.length !== 2 || args[0] === void 0 || args[1] === void 0) {
152
+ console.error("pi-ci-artifact: expected <absolute-tarball> <absolute-candidate>");
153
+ process.exit(1);
154
+ }
155
+ const [tarballArg, candidateArg] = args;
156
+ await prepareObservedPiCiArtifact({
157
+ tarballPath: tarballArg,
158
+ candidatePath: candidateArg,
159
+ fetchImpl: fetch
160
+ }).catch((error) => {
161
+ console.error(error instanceof Error ? error.message : "pi-ci-artifact: failed");
162
+ process.exit(1);
163
+ });
164
+ }
165
+ export {
166
+ prepareObservedPiCiArtifact
167
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jorgex-stack",
3
- "version": "1.9.61",
3
+ "version": "1.9.62",
4
4
  "description": "Harness multi-agente portable: instala la config JorgeX (agentes, skills, hooks, Engram, MCPs) en Claude Code, Codex CLI, OpenCode y Pi",
5
5
  "type": "module",
6
6
  "license": "MIT",