jorgex-stack 1.9.54 → 1.9.56
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/cli.d.ts +1 -0
- package/dist/cli.js +250 -25
- package/package.json +1 -1
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -359,6 +359,7 @@ function findTomlSection(lines, section) {
|
|
|
359
359
|
}
|
|
360
360
|
function upsertTomlSection(existing, section, body) {
|
|
361
361
|
const header = `[${section}]`;
|
|
362
|
+
const target = headerName(header) ?? section;
|
|
362
363
|
const block = `${header}
|
|
363
364
|
${body.trim()}
|
|
364
365
|
`;
|
|
@@ -372,7 +373,7 @@ ${body.trim()}
|
|
|
372
373
|
offset += rawLines[index].length;
|
|
373
374
|
if (index < rawLines.length - 1) offset++;
|
|
374
375
|
}
|
|
375
|
-
const found = findTomlSection(lines,
|
|
376
|
+
const found = findTomlSection(lines, target);
|
|
376
377
|
if (found === null) {
|
|
377
378
|
const sep = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
378
379
|
return existing + sep + block;
|
|
@@ -1203,11 +1204,22 @@ ${gitReadCommands.map((command) => `- \`${command}\``).join("\n")}
|
|
|
1203
1204
|
}
|
|
1204
1205
|
}
|
|
1205
1206
|
const defaults = loadCanonicalDefaults(ctx.stackDir)["opencode"];
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
"
|
|
1210
|
-
|
|
1207
|
+
const canonicalPermission = defaults?.["permission"];
|
|
1208
|
+
if (isFreshConfig) {
|
|
1209
|
+
if (canonicalPermission !== void 0) {
|
|
1210
|
+
root["permission"] = canonicalPermission;
|
|
1211
|
+
ctx.warnings.push(
|
|
1212
|
+
"OpenCode: fresh config allows ordinary reads, edits, web access and Bash; sensitive operations ask, while protected paths and obvious destruction are denied. Native matching is not a universal filesystem sandbox."
|
|
1213
|
+
);
|
|
1214
|
+
}
|
|
1215
|
+
} else if (canonicalPermission !== void 0 && !isDeepStrictEqual(root["permission"], canonicalPermission)) {
|
|
1216
|
+
if (ctx.upgradePermissions === true) {
|
|
1217
|
+
root["permission"] = canonicalPermission;
|
|
1218
|
+
} else {
|
|
1219
|
+
ctx.warnings.push(
|
|
1220
|
+
"OpenCode: permission block differs from the stack default and was left untouched; re-run with --upgrade-permissions to replace it (a backup is created first), or edit it by hand. Overwriting discards your own permission changes, including any extra hardenings."
|
|
1221
|
+
);
|
|
1222
|
+
}
|
|
1211
1223
|
}
|
|
1212
1224
|
const mcp = root["mcp"] ??= {};
|
|
1213
1225
|
for (const [name, server] of Object.entries(canonical.servers)) {
|
|
@@ -1568,12 +1580,26 @@ ${agent.body}`,
|
|
|
1568
1580
|
const settingsFile = path10.join(ctx.configDir, "settings.json");
|
|
1569
1581
|
let content = upsertNativeHooks(contentSource, canonical, scriptsDir);
|
|
1570
1582
|
const defaults = loadCanonicalDefaults(ctx.stackDir)["claude-code"];
|
|
1571
|
-
|
|
1583
|
+
const canonicalPermissions = defaults?.["permissions"];
|
|
1584
|
+
if (contentSource === null) {
|
|
1585
|
+
if (canonicalPermissions !== void 0) {
|
|
1586
|
+
content = upsertJson(content, (root) => {
|
|
1587
|
+
if (root["permissions"] === void 0) {
|
|
1588
|
+
root["permissions"] = canonicalPermissions;
|
|
1589
|
+
ctx.warnings.push(
|
|
1590
|
+
"Claude Code: fresh config enables read-anywhere via Read/Grep/Glob allow rules; shell, writes and web egress remain approval-gated, but broad local reads can expose secrets not covered by deny rules."
|
|
1591
|
+
);
|
|
1592
|
+
}
|
|
1593
|
+
});
|
|
1594
|
+
}
|
|
1595
|
+
} else if (canonicalPermissions !== void 0) {
|
|
1572
1596
|
content = upsertJson(content, (root) => {
|
|
1573
|
-
if (root["permissions"]
|
|
1574
|
-
|
|
1597
|
+
if (isDeepStrictEqual2(root["permissions"], canonicalPermissions)) return;
|
|
1598
|
+
if (ctx.upgradePermissions === true) {
|
|
1599
|
+
root["permissions"] = canonicalPermissions;
|
|
1600
|
+
} else {
|
|
1575
1601
|
ctx.warnings.push(
|
|
1576
|
-
"Claude Code:
|
|
1602
|
+
"Claude Code: permissions block differs from the stack default and was left untouched; re-run with --upgrade-permissions to replace it (a backup is created first), or edit it by hand. Overwriting discards your own permission changes, including any extra hardenings."
|
|
1577
1603
|
);
|
|
1578
1604
|
}
|
|
1579
1605
|
});
|
|
@@ -1867,6 +1893,61 @@ var CODEX_PERMISSION_SECTIONS = [
|
|
|
1867
1893
|
function renderCodexPermissionEntries(entries, quoteKeys) {
|
|
1868
1894
|
return entries.map(([key, value]) => `${quoteKeys ? JSON.stringify(key) : key} = ${JSON.stringify(value)}`).join("\n");
|
|
1869
1895
|
}
|
|
1896
|
+
var CODEX_STALE_PERMISSIONS_WARNING = "Codex: permission profile differs from the stack default and was left untouched; re-run with --upgrade-permissions to replace it (a backup is created first), or edit it by hand. Overwriting discards your own permission changes, including any extra hardenings.";
|
|
1897
|
+
function codexNormalizedHeader(header) {
|
|
1898
|
+
return headerName(`[${header}]`) ?? header;
|
|
1899
|
+
}
|
|
1900
|
+
function readCodexRootValue(config, key) {
|
|
1901
|
+
const lines = config.replace(/\r\n/g, "\n").split("\n");
|
|
1902
|
+
const mask = multilineStringMask(lines);
|
|
1903
|
+
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1904
|
+
const keyPattern = new RegExp(`^\\s*(?:${escaped}|"${escaped}"|'${escaped}')\\s*=`);
|
|
1905
|
+
for (const [index, line] of lines.entries()) {
|
|
1906
|
+
if (mask[index]) continue;
|
|
1907
|
+
if (line.trim().startsWith("[")) break;
|
|
1908
|
+
if (!keyPattern.test(line)) continue;
|
|
1909
|
+
const match = CODEX_ASSIGNMENT.exec(line.trim());
|
|
1910
|
+
return match === null ? void 0 : parseTomlString(match[2]);
|
|
1911
|
+
}
|
|
1912
|
+
return void 0;
|
|
1913
|
+
}
|
|
1914
|
+
function setCodexRootKey(config, key, value) {
|
|
1915
|
+
const eol = config.includes("\r\n") ? "\r\n" : "\n";
|
|
1916
|
+
const lines = config.replace(/\r\n/g, "\n").split("\n");
|
|
1917
|
+
const mask = multilineStringMask(lines);
|
|
1918
|
+
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1919
|
+
const keyPattern = new RegExp(`^\\s*(?:${escaped}|"${escaped}"|'${escaped}')\\s*=`);
|
|
1920
|
+
const assignment = new RegExp(
|
|
1921
|
+
`^(\\s*(?:${escaped}|"${escaped}"|'${escaped}')\\s*=\\s*)(${CODEX_JSON_STRING_ARRAY}|${CODEX_JSON_VALUE})(\\s*(?:#.*)?)$`
|
|
1922
|
+
);
|
|
1923
|
+
for (const [index, line] of lines.entries()) {
|
|
1924
|
+
if (mask[index]) continue;
|
|
1925
|
+
if (line.trim().startsWith("[")) break;
|
|
1926
|
+
if (!keyPattern.test(line)) continue;
|
|
1927
|
+
const match = assignment.exec(line);
|
|
1928
|
+
lines[index] = match === null ? `${key} = ${value}` : `${match[1]}${value}${match[3]}`;
|
|
1929
|
+
return lines.join(eol);
|
|
1930
|
+
}
|
|
1931
|
+
return upsertTomlRootKeyIfMissing(config, key, value);
|
|
1932
|
+
}
|
|
1933
|
+
function isCodexPermissionBlockCurrent(config, defaults) {
|
|
1934
|
+
const expectedApproval = defaults["approval_policy"];
|
|
1935
|
+
const expectedDefault = defaults["default_permissions"];
|
|
1936
|
+
if (typeof expectedApproval !== "string" || typeof expectedDefault !== "string") return true;
|
|
1937
|
+
if (readCodexRootValue(config, "approval_policy") !== expectedApproval) return false;
|
|
1938
|
+
if (readCodexRootValue(config, "default_permissions") !== expectedDefault) return false;
|
|
1939
|
+
return CODEX_PERMISSION_SECTIONS.every(
|
|
1940
|
+
({ header, entries, quoteKeys }) => (readTomlSection(config, codexNormalizedHeader(header)) ?? "").trim() === renderCodexPermissionEntries(entries, quoteKeys).trim()
|
|
1941
|
+
);
|
|
1942
|
+
}
|
|
1943
|
+
function reseedCodexPermissionBlock(config, defaults) {
|
|
1944
|
+
let out = setCodexRootKey(config, "approval_policy", tomlString(String(defaults["approval_policy"])));
|
|
1945
|
+
out = setCodexRootKey(out, "default_permissions", tomlString(String(defaults["default_permissions"])));
|
|
1946
|
+
for (const { header, entries, quoteKeys } of CODEX_PERMISSION_SECTIONS) {
|
|
1947
|
+
out = upsertTomlSection(out, header, renderCodexPermissionEntries(entries, quoteKeys));
|
|
1948
|
+
}
|
|
1949
|
+
return out;
|
|
1950
|
+
}
|
|
1870
1951
|
function parseCodexKey(raw) {
|
|
1871
1952
|
if (!raw.startsWith('"')) return raw;
|
|
1872
1953
|
try {
|
|
@@ -2100,6 +2181,16 @@ ${body}`
|
|
|
2100
2181
|
""
|
|
2101
2182
|
].join("\n");
|
|
2102
2183
|
}
|
|
2184
|
+
if (contentSource !== null) {
|
|
2185
|
+
const codexDefaults = loadCanonicalDefaults(ctx.stackDir)["codex"];
|
|
2186
|
+
if (codexDefaults !== void 0 && !isCodexPermissionBlockCurrent(contentSource, codexDefaults)) {
|
|
2187
|
+
if (ctx.upgradePermissions === true) {
|
|
2188
|
+
content = reseedCodexPermissionBlock(content, codexDefaults);
|
|
2189
|
+
} else {
|
|
2190
|
+
ctx.warnings.push(CODEX_STALE_PERMISSIONS_WARNING);
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2103
2194
|
if (!hasTomlRootKey(content, PRIMARY_MODEL_FIELD2)) {
|
|
2104
2195
|
content = upsertTomlRootKeyIfMissing(content, PRIMARY_MODEL_FIELD2, PRIMARY_MODEL2);
|
|
2105
2196
|
if (ctx.ownedPrimaryModelFields?.has(PRIMARY_MODEL_FIELD2) !== true) {
|
|
@@ -3229,6 +3320,7 @@ async function runInstall(opts) {
|
|
|
3229
3320
|
engramBin,
|
|
3230
3321
|
models,
|
|
3231
3322
|
warnings: [],
|
|
3323
|
+
upgradePermissions: opts.upgradePermissions === true,
|
|
3232
3324
|
enabledMcpServers: enabledMcpServers(id, opts.devtoolsMcpSelection?.[id], useManifest),
|
|
3233
3325
|
playwrightCliEnabled: projectPlaywrightPrompt ? opts.playwrightToolConsent?.runtimeSelection?.[id] ?? true : useManifest && loadPlaywrightCliPreference(playwrightCliPreferenceFile(), id) === true && (plannedPlaywright ?? true),
|
|
3234
3326
|
ownedMcpServers: ownedMcpServers(id, useManifest),
|
|
@@ -3483,6 +3575,10 @@ var REQUIRED_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
|
3483
3575
|
"runner-json-v1",
|
|
3484
3576
|
"managed-primary-model-v1"
|
|
3485
3577
|
]);
|
|
3578
|
+
var PERMISSIONS_UPGRADE_CAPABILITY = "permissions-upgrade-v1";
|
|
3579
|
+
function supportsPermissionsUpgrade(capabilities) {
|
|
3580
|
+
return Array.isArray(capabilities) && capabilities.includes(PERMISSIONS_UPGRADE_CAPABILITY);
|
|
3581
|
+
}
|
|
3486
3582
|
var ALLOWED_EXTERNAL_WRITES = /* @__PURE__ */ new Set([
|
|
3487
3583
|
"settings.json",
|
|
3488
3584
|
"models.json",
|
|
@@ -3506,6 +3602,7 @@ function managedExternalWritesAreSafe(writes, capabilities) {
|
|
|
3506
3602
|
const permissions = capabilities.includes("permissions-policy-v1");
|
|
3507
3603
|
const experience = capabilities.includes("experience-defaults-v1");
|
|
3508
3604
|
if (experience && !permissions) return false;
|
|
3605
|
+
if (supportsPermissionsUpgrade(capabilities) && !permissions) return false;
|
|
3509
3606
|
const allowed = experience ? EXPERIENCE_EXTERNAL_WRITES : permissions ? PERMISSIONS_EXTERNAL_WRITES : ALLOWED_EXTERNAL_WRITES;
|
|
3510
3607
|
if (writes.length !== allowed.size) return false;
|
|
3511
3608
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -3728,6 +3825,43 @@ function runPackageCommand(input, deps, command) {
|
|
|
3728
3825
|
if (result.exitCode !== 0) return { kind: "blocked", reason: "runner-unhealthy" };
|
|
3729
3826
|
return parseRunnerRecord(result.stdout, result.stderr, command, input.candidate, input.packageRunner) ?? { kind: "blocked", reason: "runner-output" };
|
|
3730
3827
|
}
|
|
3828
|
+
var CONFIG_LOCKED_SIGNAL = "CONFIG_LOCKED";
|
|
3829
|
+
var UPGRADE_LOCK_RETRIES = 2;
|
|
3830
|
+
function stdoutHasConfigLockedSignal(stdout) {
|
|
3831
|
+
const body = stdout.endsWith("\n") ? stdout.slice(0, -1) : stdout;
|
|
3832
|
+
if (body === "" || body.includes("\n") || body.includes("\r")) return false;
|
|
3833
|
+
try {
|
|
3834
|
+
const parsed = JSON.parse(body);
|
|
3835
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return false;
|
|
3836
|
+
const error = Reflect.get(parsed, "error");
|
|
3837
|
+
if (error === null || typeof error !== "object" || Array.isArray(error)) return false;
|
|
3838
|
+
return Reflect.get(error, "code") === CONFIG_LOCKED_SIGNAL;
|
|
3839
|
+
} catch {
|
|
3840
|
+
return false;
|
|
3841
|
+
}
|
|
3842
|
+
}
|
|
3843
|
+
function isConfigLockedFailure(result) {
|
|
3844
|
+
if (result.exitCode !== 1) return false;
|
|
3845
|
+
return stdoutHasConfigLockedSignal(result.stdout) || result.stderr.includes(CONFIG_LOCKED_SIGNAL);
|
|
3846
|
+
}
|
|
3847
|
+
function runUpgradeWithLockRetry(input, deps) {
|
|
3848
|
+
let retries = 0;
|
|
3849
|
+
for (; ; ) {
|
|
3850
|
+
const raw = deps.run({
|
|
3851
|
+
executable: input.packageRunner,
|
|
3852
|
+
args: ["upgrade", "--json"],
|
|
3853
|
+
environment: input.environment
|
|
3854
|
+
});
|
|
3855
|
+
if (raw.exitCode !== 0) {
|
|
3856
|
+
if (isConfigLockedFailure(raw) && retries < UPGRADE_LOCK_RETRIES) {
|
|
3857
|
+
retries += 1;
|
|
3858
|
+
continue;
|
|
3859
|
+
}
|
|
3860
|
+
return { kind: "blocked", reason: "runner-unhealthy" };
|
|
3861
|
+
}
|
|
3862
|
+
return parseRunnerRecord(raw.stdout, raw.stderr, "upgrade", input.candidate, input.packageRunner) ?? { kind: "blocked", reason: "runner-output" };
|
|
3863
|
+
}
|
|
3864
|
+
}
|
|
3731
3865
|
function isBlockedResult(value) {
|
|
3732
3866
|
return "kind" in value;
|
|
3733
3867
|
}
|
|
@@ -3760,7 +3894,32 @@ function executePiPackageLifecycle(input, deps) {
|
|
|
3760
3894
|
if (result === null || typeof result !== "object" || Reflect.get(result, "changed") !== true && Reflect.get(result, "changed") !== false || !Array.isArray(Reflect.get(result, "actions"))) {
|
|
3761
3895
|
return { kind: "blocked", reason: "runner-unhealthy" };
|
|
3762
3896
|
}
|
|
3763
|
-
|
|
3897
|
+
const syncActions = Reflect.get(result, "actions");
|
|
3898
|
+
if (input.upgradePermissions !== true || !supportsPermissionsUpgrade(input.candidate.contract.capabilities)) {
|
|
3899
|
+
return { kind: "synced", actions: syncActions };
|
|
3900
|
+
}
|
|
3901
|
+
const upgrade = runUpgradeWithLockRetry(input, deps);
|
|
3902
|
+
if (isBlockedResult(upgrade)) return upgrade;
|
|
3903
|
+
const upgraded = upgrade.result;
|
|
3904
|
+
if (upgraded === null || typeof upgraded !== "object" || Array.isArray(upgraded)) {
|
|
3905
|
+
return { kind: "blocked", reason: "runner-output" };
|
|
3906
|
+
}
|
|
3907
|
+
const changed = Reflect.get(upgraded, "changed");
|
|
3908
|
+
const actions = Reflect.get(upgraded, "actions");
|
|
3909
|
+
if (changed !== true && changed !== false || !Array.isArray(actions)) {
|
|
3910
|
+
return { kind: "blocked", reason: "runner-unhealthy" };
|
|
3911
|
+
}
|
|
3912
|
+
if (typeof Reflect.get(upgraded, "policy") === "string" || typeof Reflect.get(upgraded, "config") === "string") {
|
|
3913
|
+
return { kind: "blocked", reason: "runner-output" };
|
|
3914
|
+
}
|
|
3915
|
+
if (changed === true) {
|
|
3916
|
+
const policySha256 = Reflect.get(upgraded, "policySha256");
|
|
3917
|
+
if (typeof policySha256 !== "string" || !/^[a-f0-9]{64}$/.test(policySha256)) {
|
|
3918
|
+
return { kind: "blocked", reason: "runner-output" };
|
|
3919
|
+
}
|
|
3920
|
+
return { kind: "synced", actions: [...syncActions, ...actions], upgraded: true, policySha256 };
|
|
3921
|
+
}
|
|
3922
|
+
return { kind: "synced", actions: [...syncActions, ...actions], upgraded: false };
|
|
3764
3923
|
}
|
|
3765
3924
|
const models = command.result;
|
|
3766
3925
|
if (models === null || typeof models !== "object" || Reflect.get(models, "mode") !== "inherit-session" || !sameRecord(Reflect.get(models, "tiers"), ["strong", "standard", "cheap"])) {
|
|
@@ -4695,6 +4854,37 @@ function readDoctorTextIfExists(file) {
|
|
|
4695
4854
|
throw error;
|
|
4696
4855
|
}
|
|
4697
4856
|
}
|
|
4857
|
+
var STALE_PERMISSIONS_MARKER = "differs from the stack default and was left untouched";
|
|
4858
|
+
var UPGRADE_PERMISSIONS_REMEDY = "jorgex-stack sync --upgrade-permissions --dry-run";
|
|
4859
|
+
function piAgentDir(targetDir) {
|
|
4860
|
+
return targetDir === void 0 ? process.env.PI_CODING_AGENT_DIR ?? path27.join(HOME, ".pi", "agent") : path27.join(targetDir, "pi-agent");
|
|
4861
|
+
}
|
|
4862
|
+
function reportPiPermissions(targetDir) {
|
|
4863
|
+
const agentDir = piAgentDir(targetDir);
|
|
4864
|
+
const configFile = path27.join(agentDir, "extensions", "pi-permission-system", "config.json");
|
|
4865
|
+
const receiptFile = path27.join(agentDir, "jorgex-pi", "permissions-lifecycle.v1.json");
|
|
4866
|
+
let config;
|
|
4867
|
+
let receipt;
|
|
4868
|
+
try {
|
|
4869
|
+
config = readDoctorTextIfExists(configFile);
|
|
4870
|
+
receipt = readDoctorTextIfExists(receiptFile);
|
|
4871
|
+
} catch {
|
|
4872
|
+
p3.log.error(`Pi: cannot read permission state in ${agentDir}; check files and permissions.`);
|
|
4873
|
+
return 1;
|
|
4874
|
+
}
|
|
4875
|
+
if (config === null) return 0;
|
|
4876
|
+
try {
|
|
4877
|
+
JSON.parse(config);
|
|
4878
|
+
} catch {
|
|
4879
|
+
p3.log.error(`Pi: permission policy at ${configFile} is not valid JSON and was left untouched; the Pi package doctor reports it as an error.`);
|
|
4880
|
+
return 1;
|
|
4881
|
+
}
|
|
4882
|
+
if (receipt !== null) return 0;
|
|
4883
|
+
p3.log.warn(
|
|
4884
|
+
`Pi: permission policy present without package ownership (${configFile}) and left untouched; Stack never rewrites Pi state \u2014 align it by hand or remove it so a later 'jorgex-stack sync --agents pi' can seed the package default.`
|
|
4885
|
+
);
|
|
4886
|
+
return 1;
|
|
4887
|
+
}
|
|
4698
4888
|
function engramVersion(bin) {
|
|
4699
4889
|
const out = runDetectedBin(bin, ["--version"], 5e3);
|
|
4700
4890
|
if (out === null) return null;
|
|
@@ -4775,6 +4965,9 @@ async function runDoctor(options = {}) {
|
|
|
4775
4965
|
return 1;
|
|
4776
4966
|
}
|
|
4777
4967
|
let problems = reportWritingStyle(options, writingStyle, modePreference);
|
|
4968
|
+
if (options.runtimes === void 0 || options.runtimes.includes("pi")) {
|
|
4969
|
+
problems += reportPiPermissions(options.targetDir);
|
|
4970
|
+
}
|
|
4778
4971
|
if (options.targetDir !== void 0 || options.runtimes !== void 0 && options.runtimes.length > 0 && options.runtimes.every((id) => id === "pi")) {
|
|
4779
4972
|
p3.outro(problems > 0 ? `Doctor (alcance: estilo): ${problems} problema(s) \u2014 revisa arriba.` : "Doctor (alcance: estilo): todo sano.");
|
|
4780
4973
|
return problems > 0 ? 1 : 0;
|
|
@@ -4867,8 +5060,11 @@ async function runDoctor(options = {}) {
|
|
|
4867
5060
|
if (!ctx) continue;
|
|
4868
5061
|
ctx.writingStyle = writingStyle;
|
|
4869
5062
|
let pending;
|
|
5063
|
+
let stalePermissions = false;
|
|
4870
5064
|
try {
|
|
4871
|
-
|
|
5065
|
+
const plan = buildPlan(adapter, ctx);
|
|
5066
|
+
pending = diffPlan(plan).filter((d) => d.status !== "unchanged").length;
|
|
5067
|
+
stalePermissions = ctx.warnings.some((warning) => warning.includes(STALE_PERMISSIONS_MARKER));
|
|
4872
5068
|
} catch (err) {
|
|
4873
5069
|
p3.log.error(
|
|
4874
5070
|
`${adapter.name}: configuraci\xF3n incompatible o ilegible en ${detection.configDir} \u2014 ${err instanceof Error ? err.message : err}`
|
|
@@ -4876,10 +5072,16 @@ async function runDoctor(options = {}) {
|
|
|
4876
5072
|
problems++;
|
|
4877
5073
|
continue;
|
|
4878
5074
|
}
|
|
5075
|
+
if (stalePermissions) {
|
|
5076
|
+
p3.log.warn(
|
|
5077
|
+
`${adapter.name}: permission block differs from the stack default and was left untouched; preview the upgrade with '${UPGRADE_PERMISSIONS_REMEDY}'. Overwriting discards your own permission changes, including any extra hardenings.`
|
|
5078
|
+
);
|
|
5079
|
+
problems++;
|
|
5080
|
+
}
|
|
4879
5081
|
if (pending > 0) {
|
|
4880
5082
|
p3.log.warn(`${adapter.name}: ${pending} archivos gestionados desactualizados o ausentes \u2192 ejecuta 'sync'.`);
|
|
4881
5083
|
problems++;
|
|
4882
|
-
} else {
|
|
5084
|
+
} else if (!stalePermissions) {
|
|
4883
5085
|
p3.log.success(`${adapter.name}: config del stack al d\xEDa (${detection.configDir}).`);
|
|
4884
5086
|
}
|
|
4885
5087
|
const prev = manifest.runtimes[adapter.id];
|
|
@@ -6212,16 +6414,16 @@ import { createHash as createHash2 } from "crypto";
|
|
|
6212
6414
|
var pi_runtime_pin_default = {
|
|
6213
6415
|
package: {
|
|
6214
6416
|
name: "jorgex-pi",
|
|
6215
|
-
version: "0.8.
|
|
6216
|
-
source: "npm:jorgex-pi@0.8.
|
|
6417
|
+
version: "0.8.26",
|
|
6418
|
+
source: "npm:jorgex-pi@0.8.26"
|
|
6217
6419
|
},
|
|
6218
6420
|
provenance: {
|
|
6219
|
-
commit: "
|
|
6421
|
+
commit: "7d976c949e7a68d591ac01fb0f92ba83332ba291"
|
|
6220
6422
|
},
|
|
6221
6423
|
tarball: {
|
|
6222
|
-
bytes:
|
|
6223
|
-
sha256: "
|
|
6224
|
-
sha512: "
|
|
6424
|
+
bytes: 89140420,
|
|
6425
|
+
sha256: "fadac8c16ae63585db2a3bd7109ab413e24f8df076f2f79fe8e3e2c404bc8324",
|
|
6426
|
+
sha512: "a508b39b6327eef6a371c8835ab957b838779a50e102c54e24c3a205342215a302bf1056b08571d9ea6c4fb79aa93978477c68be39aea4cd3da0e7995c78a6a6"
|
|
6225
6427
|
}
|
|
6226
6428
|
};
|
|
6227
6429
|
|
|
@@ -6246,6 +6448,7 @@ var PI_RUNTIME_CANDIDATE = {
|
|
|
6246
6448
|
"engram-runtime-tools-v1",
|
|
6247
6449
|
"context7-http-v1",
|
|
6248
6450
|
"permissions-policy-v1",
|
|
6451
|
+
"permissions-upgrade-v1",
|
|
6249
6452
|
"experience-defaults-v1",
|
|
6250
6453
|
"chrome-devtools-handoff-v1",
|
|
6251
6454
|
"playwright-handoff-v1",
|
|
@@ -6258,7 +6461,7 @@ var PI_RUNTIME_CANDIDATE = {
|
|
|
6258
6461
|
],
|
|
6259
6462
|
runner: {
|
|
6260
6463
|
bin: "jorgex-pi",
|
|
6261
|
-
commands: ["status", "doctor", "models", "sync", "cleanup"],
|
|
6464
|
+
commands: ["status", "doctor", "models", "sync", "upgrade", "cleanup"],
|
|
6262
6465
|
schemaVersion: 1,
|
|
6263
6466
|
maxStdoutBytes: 65536
|
|
6264
6467
|
},
|
|
@@ -6589,7 +6792,8 @@ function runPiRuntime(input, deps) {
|
|
|
6589
6792
|
plan,
|
|
6590
6793
|
candidate: PI_RUNTIME_CANDIDATE,
|
|
6591
6794
|
packageRunner: paths.packageRunner,
|
|
6592
|
-
environment: paths.environment
|
|
6795
|
+
environment: paths.environment,
|
|
6796
|
+
...input.upgradePermissions === true ? { upgradePermissions: true } : {}
|
|
6593
6797
|
});
|
|
6594
6798
|
persistReturnedReceipt(result2, paths, deps);
|
|
6595
6799
|
return result2;
|
|
@@ -6930,8 +7134,11 @@ async function runManagedPiSystem(input) {
|
|
|
6930
7134
|
packageOnly,
|
|
6931
7135
|
writingStyle: suppliedStyle,
|
|
6932
7136
|
writingStyleMode,
|
|
7137
|
+
upgradePermissions: requestedUpgrade,
|
|
6933
7138
|
...runtimeInput
|
|
6934
7139
|
} = input;
|
|
7140
|
+
const supportsPermissionsUpgrade2 = PI_RUNTIME_CANDIDATE.contract.capabilities.includes("permissions-upgrade-v1");
|
|
7141
|
+
const upgradePermissions = requestedUpgrade === true && supportsPermissionsUpgrade2;
|
|
6935
7142
|
if (input.operation === "doctor" && packageOnly) {
|
|
6936
7143
|
const result2 = managedPackageResult(await runPiRuntimeSystem(runtimeInput));
|
|
6937
7144
|
return result2.kind === "manual-existing" ? manualExistingResult(result2) : result2;
|
|
@@ -6970,7 +7177,11 @@ async function runManagedPiSystem(input) {
|
|
|
6970
7177
|
const result = await runManagedPiOperation(input.operation, {
|
|
6971
7178
|
installInitRemedy: input.targetDir === void 0 ? void 0 : INSTALL_INIT_TARGET_REMEDY,
|
|
6972
7179
|
async runPackage(operation) {
|
|
6973
|
-
return managedPackageResult(await runPiRuntimeSystem({
|
|
7180
|
+
return managedPackageResult(await runPiRuntimeSystem({
|
|
7181
|
+
...runtimeInput,
|
|
7182
|
+
operation,
|
|
7183
|
+
...upgradePermissions ? { upgradePermissions: true } : {}
|
|
7184
|
+
}));
|
|
6974
7185
|
},
|
|
6975
7186
|
runProjection(operation) {
|
|
6976
7187
|
const result2 = runPiProjectionLifecycleSystem({
|
|
@@ -7527,6 +7738,7 @@ function parseFlags(args, allowReceipt = false) {
|
|
|
7527
7738
|
removePlaywright: false,
|
|
7528
7739
|
devtools: false,
|
|
7529
7740
|
noDevtools: false,
|
|
7741
|
+
upgradePermissions: false,
|
|
7530
7742
|
receipt: void 0,
|
|
7531
7743
|
positional: [],
|
|
7532
7744
|
unknownFlags: []
|
|
@@ -7596,6 +7808,7 @@ function parseFlags(args, allowReceipt = false) {
|
|
|
7596
7808
|
else if (arg === "--remove-playwright") flags.removePlaywright = true;
|
|
7597
7809
|
else if (arg === "--devtools") flags.devtools = true;
|
|
7598
7810
|
else if (arg === "--no-devtools") flags.noDevtools = true;
|
|
7811
|
+
else if (arg === "--upgrade-permissions") flags.upgradePermissions = true;
|
|
7599
7812
|
else if (arg.startsWith("-")) flags.unknownFlags.push(arg);
|
|
7600
7813
|
else flags.positional.push(arg);
|
|
7601
7814
|
}
|
|
@@ -7886,7 +8099,16 @@ async function runSelectedPi(options) {
|
|
|
7886
8099
|
engramBin,
|
|
7887
8100
|
...devtoolsMcpEnabled === void 0 ? {} : { devtoolsMcpEnabled },
|
|
7888
8101
|
...playwrightCliEnabled === void 0 ? {} : { playwrightCliEnabled },
|
|
7889
|
-
...playwrightCapability === void 0 ? {} : { playwrightCapability }
|
|
8102
|
+
...playwrightCapability === void 0 ? {} : { playwrightCapability },
|
|
8103
|
+
...(() => {
|
|
8104
|
+
if (options.upgradePermissions !== true) return {};
|
|
8105
|
+
const supports = PI_RUNTIME_CANDIDATE.contract.capabilities.includes("permissions-upgrade-v1");
|
|
8106
|
+
if (!supports) {
|
|
8107
|
+
p6.log.info("Pi: --upgrade-permissions requiere un paquete con permissions-upgrade-v1; se contin\xFAa en modo seed-only.");
|
|
8108
|
+
return {};
|
|
8109
|
+
}
|
|
8110
|
+
return { upgradePermissions: true };
|
|
8111
|
+
})()
|
|
7890
8112
|
});
|
|
7891
8113
|
if (result.kind === "blocked") {
|
|
7892
8114
|
const paths = "paths" in result ? `: ${result.paths.join(", ")}` : "";
|
|
@@ -7929,6 +8151,7 @@ Opciones:
|
|
|
7929
8151
|
--engram (install) autoriza instalar el binario Engram si falta
|
|
7930
8152
|
--devtools (install/sync) activa Chrome DevTools MCP para los runtimes destino (opt-in)
|
|
7931
8153
|
--no-devtools (install/sync) desactiva Chrome DevTools MCP (incompatible con --devtools)
|
|
8154
|
+
--upgrade-permissions (install/sync) re-aplica permisos gestionados sobre config existente (opt-in)
|
|
7932
8155
|
--remove-engram (uninstall) desregistra Engram de los runtimes;
|
|
7933
8156
|
memorias y binario quedan intactos igualmente
|
|
7934
8157
|
--playwright-runtimes <csv> Activa su gu\xEDa s\xF3lo en estos runtimes de --agents (con --playwright)
|
|
@@ -7978,7 +8201,7 @@ Flags disponibles: jorgex-stack --help`
|
|
|
7978
8201
|
}
|
|
7979
8202
|
switch (command) {
|
|
7980
8203
|
case "quality": {
|
|
7981
|
-
if (flags.targetDir !== void 0 || flags.agents.length > 0 || flags.dryRun || flags.yes || flags.mode !== void 0 || flags.subagentConcurrency !== void 0 || flags.list || flags.check || flags.removeEngram || flags.engram || flags.playwright || flags.removePlaywright || flags.devtools || flags.noDevtools) {
|
|
8204
|
+
if (flags.targetDir !== void 0 || flags.agents.length > 0 || flags.dryRun || flags.yes || flags.mode !== void 0 || flags.subagentConcurrency !== void 0 || flags.list || flags.check || flags.removeEngram || flags.engram || flags.playwright || flags.removePlaywright || flags.devtools || flags.noDevtools || flags.upgradePermissions) {
|
|
7982
8205
|
console.error("quality solo admite <plan.json> y, opcionalmente, --receipt <path>.");
|
|
7983
8206
|
process.exitCode = 1;
|
|
7984
8207
|
return;
|
|
@@ -8081,6 +8304,7 @@ Flags disponibles: jorgex-stack --help`
|
|
|
8081
8304
|
playwrightToolConsent,
|
|
8082
8305
|
devtoolsMcpSelection,
|
|
8083
8306
|
engramBin,
|
|
8307
|
+
upgradePermissions: flags.upgradePermissions,
|
|
8084
8308
|
...playwrightCapability === void 0 ? {} : { playwrightCapability },
|
|
8085
8309
|
...playwrightToolPlan.actions.length === 0 ? {} : { onPlaywrightCapability: capturePlaywrightCapability },
|
|
8086
8310
|
showSummary: false
|
|
@@ -8119,7 +8343,8 @@ Flags disponibles: jorgex-stack --help`
|
|
|
8119
8343
|
writingStyle,
|
|
8120
8344
|
modePreference: mode,
|
|
8121
8345
|
playwrightCliEnabled: flags.targetDir === void 0 && exitCode === 0 && playwrightToolPlan.actions.length > 0 ? playwrightToolConsent.runtimeSelection?.pi : void 0,
|
|
8122
|
-
playwrightCapability
|
|
8346
|
+
playwrightCapability,
|
|
8347
|
+
...flags.upgradePermissions ? { upgradePermissions: true } : {}
|
|
8123
8348
|
});
|
|
8124
8349
|
exitCode = Math.max(exitCode, piExitCode);
|
|
8125
8350
|
piStatus = piExitCode === 0 ? "ok" : "failed";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jorgex-stack",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.56",
|
|
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",
|