@openplaybooks/converge 0.2.2 → 0.2.3
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/examples-catalog.json +55 -0
- package/dist/index.js +389 -144
- package/package.json +5 -5
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"examples": {
|
|
4
|
+
"acp-demo": {
|
|
5
|
+
"description": "ACP (Claude Agent SDK) provider demo — programmatic agent invocation",
|
|
6
|
+
"playbookName": "default",
|
|
7
|
+
"hasApiKeys": true
|
|
8
|
+
},
|
|
9
|
+
"data-pipeline": {
|
|
10
|
+
"description": "Sequential pipeline: fetch → transform → validate",
|
|
11
|
+
"playbookName": "default",
|
|
12
|
+
"hasApiKeys": false
|
|
13
|
+
},
|
|
14
|
+
"deep-research": {
|
|
15
|
+
"description": "Layered iterative-deepening research with quality-gated progression",
|
|
16
|
+
"playbookName": "deep-research",
|
|
17
|
+
"hasApiKeys": true
|
|
18
|
+
},
|
|
19
|
+
"evolutionary-optimization": {
|
|
20
|
+
"description": "Fitness-landscape search for prompt tuning and hyperparameter sweeps",
|
|
21
|
+
"playbookName": "default",
|
|
22
|
+
"hasApiKeys": false
|
|
23
|
+
},
|
|
24
|
+
"flutter-app": {
|
|
25
|
+
"description": "Autonomous Flutter mobile app generation — design system → screens → wiring",
|
|
26
|
+
"playbookName": "default",
|
|
27
|
+
"hasApiKeys": true
|
|
28
|
+
},
|
|
29
|
+
"frontier-research": {
|
|
30
|
+
"description": "Beam-search frontier research with parallel beams and convergence tracking",
|
|
31
|
+
"playbookName": "default",
|
|
32
|
+
"hasApiKeys": false
|
|
33
|
+
},
|
|
34
|
+
"fullstack-app": {
|
|
35
|
+
"description": "Seed-driven dynamic backend + frontend generation",
|
|
36
|
+
"playbookName": "default",
|
|
37
|
+
"hasApiKeys": false
|
|
38
|
+
},
|
|
39
|
+
"hello-world": {
|
|
40
|
+
"description": "Simplest possible playbook — one task, two checks",
|
|
41
|
+
"playbookName": "default",
|
|
42
|
+
"hasApiKeys": false
|
|
43
|
+
},
|
|
44
|
+
"scientific-research": {
|
|
45
|
+
"description": "Bayesian reasoning, GRADE evidence, meta-analysis — 8-phase epoch loop",
|
|
46
|
+
"playbookName": "default",
|
|
47
|
+
"hasApiKeys": false
|
|
48
|
+
},
|
|
49
|
+
"social-sim": {
|
|
50
|
+
"description": "Persona-driven OASIS-style social simulation with tick-based iteration",
|
|
51
|
+
"playbookName": "social-sim",
|
|
52
|
+
"hasApiKeys": true
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -13877,19 +13877,33 @@ function createStoragePaths(convergeDir = ".converge") {
|
|
|
13877
13877
|
taskLog: (playbookId, taskId) => `${convergeDir}/playbooks/${playbookId}/tasks/${taskId}.log.md`
|
|
13878
13878
|
};
|
|
13879
13879
|
}
|
|
13880
|
-
function interpolateEnv(
|
|
13881
|
-
|
|
13882
|
-
|
|
13883
|
-
|
|
13884
|
-
|
|
13885
|
-
|
|
13886
|
-
|
|
13887
|
-
|
|
13888
|
-
|
|
13889
|
-
|
|
13890
|
-
|
|
13880
|
+
function interpolateEnv(value, sourcePath, allowMissing) {
|
|
13881
|
+
if (typeof value === "string") {
|
|
13882
|
+
return value.replace(
|
|
13883
|
+
/\$(\$)|\$\{([A-Z0-9_]+)(?::-([^}]*))?\}/g,
|
|
13884
|
+
(_match, dollar, name, fallback) => {
|
|
13885
|
+
if (dollar) return "$";
|
|
13886
|
+
const envValue = process.env[name];
|
|
13887
|
+
if (envValue !== void 0) return envValue;
|
|
13888
|
+
if (fallback !== void 0) return fallback;
|
|
13889
|
+
if (allowMissing) return "";
|
|
13890
|
+
throw new Error(
|
|
13891
|
+
`${sourcePath}: ${name} is not set. Add it to .env.local or export it before running the CLI.`
|
|
13892
|
+
);
|
|
13893
|
+
}
|
|
13894
|
+
);
|
|
13895
|
+
}
|
|
13896
|
+
if (Array.isArray(value)) {
|
|
13897
|
+
return value.map((v22) => interpolateEnv(v22, sourcePath, allowMissing));
|
|
13898
|
+
}
|
|
13899
|
+
if (value && typeof value === "object") {
|
|
13900
|
+
const out = {};
|
|
13901
|
+
for (const [k102, v22] of Object.entries(value)) {
|
|
13902
|
+
out[k102] = interpolateEnv(v22, sourcePath, allowMissing);
|
|
13891
13903
|
}
|
|
13892
|
-
|
|
13904
|
+
return out;
|
|
13905
|
+
}
|
|
13906
|
+
return value;
|
|
13893
13907
|
}
|
|
13894
13908
|
function createFilesystemStorage(convergeDir = ".converge") {
|
|
13895
13909
|
return new FilesystemStorage(convergeDir);
|
|
@@ -13914,7 +13928,7 @@ async function findConvergeConfig(startDir) {
|
|
|
13914
13928
|
dir = parent;
|
|
13915
13929
|
}
|
|
13916
13930
|
}
|
|
13917
|
-
async function loadProjectMdConfig(configPath) {
|
|
13931
|
+
async function loadProjectMdConfig(configPath, opts = {}) {
|
|
13918
13932
|
let raw;
|
|
13919
13933
|
try {
|
|
13920
13934
|
raw = await readFile(configPath, "utf-8");
|
|
@@ -13944,11 +13958,16 @@ See PROJECT.md format reference.`
|
|
|
13944
13958
|
See PROJECT.md format reference.`
|
|
13945
13959
|
);
|
|
13946
13960
|
}
|
|
13961
|
+
frontmatter = substituteEnvVarsInTree(
|
|
13962
|
+
frontmatter,
|
|
13963
|
+
configPath,
|
|
13964
|
+
opts.allowMissingEnv ?? false
|
|
13965
|
+
);
|
|
13947
13966
|
const body = raw.slice(match2[0].length).trim();
|
|
13948
13967
|
const projectDir = dirname(dirname(configPath));
|
|
13949
13968
|
return buildConfigFromData(frontmatter, projectDir, body);
|
|
13950
13969
|
}
|
|
13951
|
-
async function loadProjectYamlConfig(configPath) {
|
|
13970
|
+
async function loadProjectYamlConfig(configPath, opts = {}) {
|
|
13952
13971
|
let raw;
|
|
13953
13972
|
try {
|
|
13954
13973
|
raw = await readFile(configPath, "utf-8");
|
|
@@ -13958,18 +13977,6 @@ async function loadProjectYamlConfig(configPath) {
|
|
|
13958
13977
|
${err.message}`
|
|
13959
13978
|
);
|
|
13960
13979
|
}
|
|
13961
|
-
raw = raw.replace(
|
|
13962
|
-
/\$(\$)|\$\{([A-Z0-9_]+)(?::-([^}]*))?\}/g,
|
|
13963
|
-
(_m, dollar, name, fallback) => {
|
|
13964
|
-
if (dollar) return "$";
|
|
13965
|
-
const value = process.env[name];
|
|
13966
|
-
if (value !== void 0) return value;
|
|
13967
|
-
if (fallback !== void 0) return fallback;
|
|
13968
|
-
throw new Error(
|
|
13969
|
-
`${configPath}: ${name} is not set. Add it to .env.local or export it before running the CLI.`
|
|
13970
|
-
);
|
|
13971
|
-
}
|
|
13972
|
-
);
|
|
13973
13980
|
let data;
|
|
13974
13981
|
try {
|
|
13975
13982
|
data = parse(raw);
|
|
@@ -13983,9 +13990,44 @@ async function loadProjectYamlConfig(configPath) {
|
|
|
13983
13990
|
See project.yaml format reference.`
|
|
13984
13991
|
);
|
|
13985
13992
|
}
|
|
13993
|
+
data = substituteEnvVarsInTree(
|
|
13994
|
+
data,
|
|
13995
|
+
configPath,
|
|
13996
|
+
opts.allowMissingEnv ?? false
|
|
13997
|
+
);
|
|
13986
13998
|
const projectDir = dirname(dirname(configPath));
|
|
13987
13999
|
return buildConfigFromData(data, projectDir);
|
|
13988
14000
|
}
|
|
14001
|
+
function substituteEnvVarsInTree(value, configPath, allowMissingEnv) {
|
|
14002
|
+
if (typeof value === "string") {
|
|
14003
|
+
return value.replace(
|
|
14004
|
+
/\$(\$)|\$\{([A-Z0-9_]+)(?::-([^}]*))?\}/g,
|
|
14005
|
+
(_m, dollar, name, fallback) => {
|
|
14006
|
+
if (dollar) return "$";
|
|
14007
|
+
const envValue = process.env[name];
|
|
14008
|
+
if (envValue !== void 0) return envValue;
|
|
14009
|
+
if (fallback !== void 0) return fallback;
|
|
14010
|
+
if (allowMissingEnv) return "";
|
|
14011
|
+
throw new Error(
|
|
14012
|
+
`${configPath}: ${name} is not set. Add it to .env.local or export it before running the CLI.`
|
|
14013
|
+
);
|
|
14014
|
+
}
|
|
14015
|
+
);
|
|
14016
|
+
}
|
|
14017
|
+
if (Array.isArray(value)) {
|
|
14018
|
+
return value.map(
|
|
14019
|
+
(v22) => substituteEnvVarsInTree(v22, configPath, allowMissingEnv)
|
|
14020
|
+
);
|
|
14021
|
+
}
|
|
14022
|
+
if (value && typeof value === "object") {
|
|
14023
|
+
const out = {};
|
|
14024
|
+
for (const [k102, v22] of Object.entries(value)) {
|
|
14025
|
+
out[k102] = substituteEnvVarsInTree(v22, configPath, allowMissingEnv);
|
|
14026
|
+
}
|
|
14027
|
+
return out;
|
|
14028
|
+
}
|
|
14029
|
+
return value;
|
|
14030
|
+
}
|
|
13989
14031
|
function buildConfigFromData(data, projectDir, body) {
|
|
13990
14032
|
const config = {
|
|
13991
14033
|
name: data.name,
|
|
@@ -14012,12 +14054,12 @@ function buildConfigFromData(data, projectDir, body) {
|
|
|
14012
14054
|
}
|
|
14013
14055
|
return config;
|
|
14014
14056
|
}
|
|
14015
|
-
async function loadConvergeConfig(configPath, type2) {
|
|
14057
|
+
async function loadConvergeConfig(configPath, type2, opts = {}) {
|
|
14016
14058
|
const configType = type2 || (configPath.endsWith("project.yaml") || configPath.endsWith("project.yml") ? "project.yaml" : "PROJECT.md");
|
|
14017
14059
|
if (configType === "project.yaml") {
|
|
14018
|
-
return loadProjectYamlConfig(configPath);
|
|
14060
|
+
return loadProjectYamlConfig(configPath, opts);
|
|
14019
14061
|
} else {
|
|
14020
|
-
return loadProjectMdConfig(configPath);
|
|
14062
|
+
return loadProjectMdConfig(configPath, opts);
|
|
14021
14063
|
}
|
|
14022
14064
|
}
|
|
14023
14065
|
function convertScriptHooks(hooks, projectDir) {
|
|
@@ -14074,10 +14116,13 @@ function buildSafePayload(event, payload) {
|
|
|
14074
14116
|
}
|
|
14075
14117
|
return safe;
|
|
14076
14118
|
}
|
|
14077
|
-
async function resolveConvergeConfig(startDir) {
|
|
14119
|
+
async function resolveConvergeConfig(startDir, opts = {}) {
|
|
14078
14120
|
const result = await findConvergeConfig(startDir);
|
|
14079
14121
|
if (!result) return null;
|
|
14080
|
-
const
|
|
14122
|
+
const effective = {
|
|
14123
|
+
allowMissingEnv: opts.allowMissingEnv ?? process.env.CONVERGE_ALLOW_MISSING_ENV === "1"
|
|
14124
|
+
};
|
|
14125
|
+
const config = await loadConvergeConfig(result.path, result.type, effective);
|
|
14081
14126
|
return { config, configPath: result.path, type: result.type };
|
|
14082
14127
|
}
|
|
14083
14128
|
function readEnvValue(varName) {
|
|
@@ -44069,13 +44114,22 @@ checkpoints/*.yaml
|
|
|
44069
44114
|
/* Project Configuration */
|
|
44070
44115
|
/* ────────────────────────────────────────────────────────────── */
|
|
44071
44116
|
/**
|
|
44072
|
-
* Read project configuration
|
|
44117
|
+
* Read project configuration.
|
|
44118
|
+
*
|
|
44119
|
+
* `allowMissingEnv` skips throwing on unset ${VAR} placeholders — used by
|
|
44120
|
+
* `--dry` and `converge doctor`, which validate config shape without
|
|
44121
|
+
* requiring credentials.
|
|
44073
44122
|
*/
|
|
44074
|
-
readProject() {
|
|
44123
|
+
readProject(opts = {}) {
|
|
44075
44124
|
const content = readFileSync(this.paths.project, "utf8");
|
|
44076
|
-
const
|
|
44077
|
-
const
|
|
44078
|
-
|
|
44125
|
+
const parsed = parse(content);
|
|
44126
|
+
const allowMissing = opts.allowMissingEnv ?? process.env.CONVERGE_ALLOW_MISSING_ENV === "1";
|
|
44127
|
+
const interpolated = interpolateEnv(
|
|
44128
|
+
parsed,
|
|
44129
|
+
this.paths.project,
|
|
44130
|
+
allowMissing
|
|
44131
|
+
);
|
|
44132
|
+
return ProjectConfigSchema.parse(interpolated);
|
|
44079
44133
|
}
|
|
44080
44134
|
/**
|
|
44081
44135
|
* Write project configuration
|
|
@@ -73936,19 +73990,33 @@ function createStoragePaths2(convergeDir = ".converge") {
|
|
|
73936
73990
|
taskLog: (playbookId, taskId) => `${convergeDir}/playbooks/${playbookId}/tasks/${taskId}.log.md`
|
|
73937
73991
|
};
|
|
73938
73992
|
}
|
|
73939
|
-
function interpolateEnv2(
|
|
73940
|
-
|
|
73941
|
-
|
|
73942
|
-
|
|
73943
|
-
|
|
73944
|
-
|
|
73945
|
-
|
|
73946
|
-
|
|
73947
|
-
|
|
73948
|
-
|
|
73949
|
-
|
|
73993
|
+
function interpolateEnv2(value, sourcePath, allowMissing) {
|
|
73994
|
+
if (typeof value === "string") {
|
|
73995
|
+
return value.replace(
|
|
73996
|
+
/\$(\$)|\$\{([A-Z0-9_]+)(?::-([^}]*))?\}/g,
|
|
73997
|
+
(_match, dollar, name, fallback) => {
|
|
73998
|
+
if (dollar) return "$";
|
|
73999
|
+
const envValue = process.env[name];
|
|
74000
|
+
if (envValue !== void 0) return envValue;
|
|
74001
|
+
if (fallback !== void 0) return fallback;
|
|
74002
|
+
if (allowMissing) return "";
|
|
74003
|
+
throw new Error(
|
|
74004
|
+
`${sourcePath}: ${name} is not set. Add it to .env.local or export it before running the CLI.`
|
|
74005
|
+
);
|
|
74006
|
+
}
|
|
74007
|
+
);
|
|
74008
|
+
}
|
|
74009
|
+
if (Array.isArray(value)) {
|
|
74010
|
+
return value.map((v18) => interpolateEnv2(v18, sourcePath, allowMissing));
|
|
74011
|
+
}
|
|
74012
|
+
if (value && typeof value === "object") {
|
|
74013
|
+
const out = {};
|
|
74014
|
+
for (const [k19, v18] of Object.entries(value)) {
|
|
74015
|
+
out[k19] = interpolateEnv2(v18, sourcePath, allowMissing);
|
|
73950
74016
|
}
|
|
73951
|
-
|
|
74017
|
+
return out;
|
|
74018
|
+
}
|
|
74019
|
+
return value;
|
|
73952
74020
|
}
|
|
73953
74021
|
var dynamicImport2 = new Function(
|
|
73954
74022
|
"p",
|
|
@@ -74005,13 +74073,22 @@ checkpoints/*.yaml
|
|
|
74005
74073
|
/* Project Configuration */
|
|
74006
74074
|
/* ────────────────────────────────────────────────────────────── */
|
|
74007
74075
|
/**
|
|
74008
|
-
* Read project configuration
|
|
74076
|
+
* Read project configuration.
|
|
74077
|
+
*
|
|
74078
|
+
* `allowMissingEnv` skips throwing on unset ${VAR} placeholders — used by
|
|
74079
|
+
* `--dry` and `converge doctor`, which validate config shape without
|
|
74080
|
+
* requiring credentials.
|
|
74009
74081
|
*/
|
|
74010
|
-
readProject() {
|
|
74082
|
+
readProject(opts = {}) {
|
|
74011
74083
|
const content = readFileSync(this.paths.project, "utf8");
|
|
74012
|
-
const
|
|
74013
|
-
const
|
|
74014
|
-
|
|
74084
|
+
const parsed = parse(content);
|
|
74085
|
+
const allowMissing = opts.allowMissingEnv ?? process.env.CONVERGE_ALLOW_MISSING_ENV === "1";
|
|
74086
|
+
const interpolated = interpolateEnv2(
|
|
74087
|
+
parsed,
|
|
74088
|
+
this.paths.project,
|
|
74089
|
+
allowMissing
|
|
74090
|
+
);
|
|
74091
|
+
return ProjectConfigSchema2.parse(interpolated);
|
|
74015
74092
|
}
|
|
74016
74093
|
/**
|
|
74017
74094
|
* Write project configuration
|
|
@@ -98108,19 +98185,33 @@ var init_types23 = __esm3({
|
|
|
98108
98185
|
});
|
|
98109
98186
|
}
|
|
98110
98187
|
});
|
|
98111
|
-
function interpolateEnv3(
|
|
98112
|
-
|
|
98113
|
-
|
|
98114
|
-
|
|
98115
|
-
|
|
98116
|
-
|
|
98117
|
-
|
|
98118
|
-
|
|
98119
|
-
|
|
98120
|
-
|
|
98121
|
-
|
|
98188
|
+
function interpolateEnv3(value, sourcePath, allowMissing) {
|
|
98189
|
+
if (typeof value === "string") {
|
|
98190
|
+
return value.replace(
|
|
98191
|
+
/\$(\$)|\$\{([A-Z0-9_]+)(?::-([^}]*))?\}/g,
|
|
98192
|
+
(_match, dollar, name, fallback) => {
|
|
98193
|
+
if (dollar) return "$";
|
|
98194
|
+
const envValue = process.env[name];
|
|
98195
|
+
if (envValue !== void 0) return envValue;
|
|
98196
|
+
if (fallback !== void 0) return fallback;
|
|
98197
|
+
if (allowMissing) return "";
|
|
98198
|
+
throw new Error(
|
|
98199
|
+
`${sourcePath}: ${name} is not set. Add it to .env.local or export it before running the CLI.`
|
|
98200
|
+
);
|
|
98201
|
+
}
|
|
98202
|
+
);
|
|
98203
|
+
}
|
|
98204
|
+
if (Array.isArray(value)) {
|
|
98205
|
+
return value.map((v22) => interpolateEnv3(v22, sourcePath, allowMissing));
|
|
98206
|
+
}
|
|
98207
|
+
if (value && typeof value === "object") {
|
|
98208
|
+
const out = {};
|
|
98209
|
+
for (const [k102, v22] of Object.entries(value)) {
|
|
98210
|
+
out[k102] = interpolateEnv3(v22, sourcePath, allowMissing);
|
|
98122
98211
|
}
|
|
98123
|
-
|
|
98212
|
+
return out;
|
|
98213
|
+
}
|
|
98214
|
+
return value;
|
|
98124
98215
|
}
|
|
98125
98216
|
var dynamicImport3;
|
|
98126
98217
|
var FilesystemStorage3;
|
|
@@ -98183,13 +98274,22 @@ checkpoints/*.yaml
|
|
|
98183
98274
|
/* Project Configuration */
|
|
98184
98275
|
/* ────────────────────────────────────────────────────────────── */
|
|
98185
98276
|
/**
|
|
98186
|
-
* Read project configuration
|
|
98277
|
+
* Read project configuration.
|
|
98278
|
+
*
|
|
98279
|
+
* `allowMissingEnv` skips throwing on unset ${VAR} placeholders — used by
|
|
98280
|
+
* `--dry` and `converge doctor`, which validate config shape without
|
|
98281
|
+
* requiring credentials.
|
|
98187
98282
|
*/
|
|
98188
|
-
readProject() {
|
|
98283
|
+
readProject(opts = {}) {
|
|
98189
98284
|
const content = readFileSync(this.paths.project, "utf8");
|
|
98190
|
-
const
|
|
98191
|
-
const
|
|
98192
|
-
|
|
98285
|
+
const parsed = parse(content);
|
|
98286
|
+
const allowMissing = opts.allowMissingEnv ?? process.env.CONVERGE_ALLOW_MISSING_ENV === "1";
|
|
98287
|
+
const interpolated = interpolateEnv3(
|
|
98288
|
+
parsed,
|
|
98289
|
+
this.paths.project,
|
|
98290
|
+
allowMissing
|
|
98291
|
+
);
|
|
98292
|
+
return ProjectConfigSchema3.parse(interpolated);
|
|
98193
98293
|
}
|
|
98194
98294
|
/**
|
|
98195
98295
|
* Write project configuration
|
|
@@ -98505,7 +98605,7 @@ ${message}
|
|
|
98505
98605
|
};
|
|
98506
98606
|
}
|
|
98507
98607
|
});
|
|
98508
|
-
async function loadProjectMdConfig2(configPath) {
|
|
98608
|
+
async function loadProjectMdConfig2(configPath, opts = {}) {
|
|
98509
98609
|
let raw;
|
|
98510
98610
|
try {
|
|
98511
98611
|
raw = await readFile(configPath, "utf-8");
|
|
@@ -98535,11 +98635,16 @@ See PROJECT.md format reference.`
|
|
|
98535
98635
|
See PROJECT.md format reference.`
|
|
98536
98636
|
);
|
|
98537
98637
|
}
|
|
98638
|
+
frontmatter = substituteEnvVarsInTree2(
|
|
98639
|
+
frontmatter,
|
|
98640
|
+
configPath,
|
|
98641
|
+
opts.allowMissingEnv ?? false
|
|
98642
|
+
);
|
|
98538
98643
|
const body = raw.slice(match2[0].length).trim();
|
|
98539
98644
|
const projectDir = dirname(dirname(configPath));
|
|
98540
98645
|
return buildConfigFromData2(frontmatter, projectDir, body);
|
|
98541
98646
|
}
|
|
98542
|
-
async function loadProjectYamlConfig2(configPath) {
|
|
98647
|
+
async function loadProjectYamlConfig2(configPath, opts = {}) {
|
|
98543
98648
|
let raw;
|
|
98544
98649
|
try {
|
|
98545
98650
|
raw = await readFile(configPath, "utf-8");
|
|
@@ -98549,18 +98654,6 @@ async function loadProjectYamlConfig2(configPath) {
|
|
|
98549
98654
|
${err.message}`
|
|
98550
98655
|
);
|
|
98551
98656
|
}
|
|
98552
|
-
raw = raw.replace(
|
|
98553
|
-
/\$(\$)|\$\{([A-Z0-9_]+)(?::-([^}]*))?\}/g,
|
|
98554
|
-
(_m, dollar, name, fallback) => {
|
|
98555
|
-
if (dollar) return "$";
|
|
98556
|
-
const value = process.env[name];
|
|
98557
|
-
if (value !== void 0) return value;
|
|
98558
|
-
if (fallback !== void 0) return fallback;
|
|
98559
|
-
throw new Error(
|
|
98560
|
-
`${configPath}: ${name} is not set. Add it to .env.local or export it before running the CLI.`
|
|
98561
|
-
);
|
|
98562
|
-
}
|
|
98563
|
-
);
|
|
98564
98657
|
let data;
|
|
98565
98658
|
try {
|
|
98566
98659
|
data = parse(raw);
|
|
@@ -98574,9 +98667,44 @@ async function loadProjectYamlConfig2(configPath) {
|
|
|
98574
98667
|
See project.yaml format reference.`
|
|
98575
98668
|
);
|
|
98576
98669
|
}
|
|
98670
|
+
data = substituteEnvVarsInTree2(
|
|
98671
|
+
data,
|
|
98672
|
+
configPath,
|
|
98673
|
+
opts.allowMissingEnv ?? false
|
|
98674
|
+
);
|
|
98577
98675
|
const projectDir = dirname(dirname(configPath));
|
|
98578
98676
|
return buildConfigFromData2(data, projectDir);
|
|
98579
98677
|
}
|
|
98678
|
+
function substituteEnvVarsInTree2(value, configPath, allowMissingEnv) {
|
|
98679
|
+
if (typeof value === "string") {
|
|
98680
|
+
return value.replace(
|
|
98681
|
+
/\$(\$)|\$\{([A-Z0-9_]+)(?::-([^}]*))?\}/g,
|
|
98682
|
+
(_m, dollar, name, fallback) => {
|
|
98683
|
+
if (dollar) return "$";
|
|
98684
|
+
const envValue = process.env[name];
|
|
98685
|
+
if (envValue !== void 0) return envValue;
|
|
98686
|
+
if (fallback !== void 0) return fallback;
|
|
98687
|
+
if (allowMissingEnv) return "";
|
|
98688
|
+
throw new Error(
|
|
98689
|
+
`${configPath}: ${name} is not set. Add it to .env.local or export it before running the CLI.`
|
|
98690
|
+
);
|
|
98691
|
+
}
|
|
98692
|
+
);
|
|
98693
|
+
}
|
|
98694
|
+
if (Array.isArray(value)) {
|
|
98695
|
+
return value.map(
|
|
98696
|
+
(v22) => substituteEnvVarsInTree2(v22, configPath, allowMissingEnv)
|
|
98697
|
+
);
|
|
98698
|
+
}
|
|
98699
|
+
if (value && typeof value === "object") {
|
|
98700
|
+
const out = {};
|
|
98701
|
+
for (const [k102, v22] of Object.entries(value)) {
|
|
98702
|
+
out[k102] = substituteEnvVarsInTree2(v22, configPath, allowMissingEnv);
|
|
98703
|
+
}
|
|
98704
|
+
return out;
|
|
98705
|
+
}
|
|
98706
|
+
return value;
|
|
98707
|
+
}
|
|
98580
98708
|
function buildConfigFromData2(data, projectDir, body) {
|
|
98581
98709
|
const config = {
|
|
98582
98710
|
name: data.name,
|
|
@@ -98603,12 +98731,12 @@ function buildConfigFromData2(data, projectDir, body) {
|
|
|
98603
98731
|
}
|
|
98604
98732
|
return config;
|
|
98605
98733
|
}
|
|
98606
|
-
async function loadConvergeConfig2(configPath, type2) {
|
|
98734
|
+
async function loadConvergeConfig2(configPath, type2, opts = {}) {
|
|
98607
98735
|
const configType = configPath.endsWith("project.yaml") || configPath.endsWith("project.yml") ? "project.yaml" : "PROJECT.md";
|
|
98608
98736
|
if (configType === "project.yaml") {
|
|
98609
|
-
return loadProjectYamlConfig2(configPath);
|
|
98737
|
+
return loadProjectYamlConfig2(configPath, opts);
|
|
98610
98738
|
} else {
|
|
98611
|
-
return loadProjectMdConfig2(configPath);
|
|
98739
|
+
return loadProjectMdConfig2(configPath, opts);
|
|
98612
98740
|
}
|
|
98613
98741
|
}
|
|
98614
98742
|
function convertScriptHooks2(hooks, projectDir) {
|
|
@@ -139658,19 +139786,33 @@ var init_types24 = __esm4({
|
|
|
139658
139786
|
});
|
|
139659
139787
|
}
|
|
139660
139788
|
});
|
|
139661
|
-
function interpolateEnv4(
|
|
139662
|
-
|
|
139663
|
-
|
|
139664
|
-
|
|
139665
|
-
|
|
139666
|
-
|
|
139667
|
-
|
|
139668
|
-
|
|
139669
|
-
|
|
139670
|
-
|
|
139671
|
-
|
|
139789
|
+
function interpolateEnv4(value, sourcePath, allowMissing) {
|
|
139790
|
+
if (typeof value === "string") {
|
|
139791
|
+
return value.replace(
|
|
139792
|
+
/\$(\$)|\$\{([A-Z0-9_]+)(?::-([^}]*))?\}/g,
|
|
139793
|
+
(_match, dollar, name, fallback) => {
|
|
139794
|
+
if (dollar) return "$";
|
|
139795
|
+
const envValue = process.env[name];
|
|
139796
|
+
if (envValue !== void 0) return envValue;
|
|
139797
|
+
if (fallback !== void 0) return fallback;
|
|
139798
|
+
if (allowMissing) return "";
|
|
139799
|
+
throw new Error(
|
|
139800
|
+
`${sourcePath}: ${name} is not set. Add it to .env.local or export it before running the CLI.`
|
|
139801
|
+
);
|
|
139802
|
+
}
|
|
139803
|
+
);
|
|
139804
|
+
}
|
|
139805
|
+
if (Array.isArray(value)) {
|
|
139806
|
+
return value.map((v22) => interpolateEnv4(v22, sourcePath, allowMissing));
|
|
139807
|
+
}
|
|
139808
|
+
if (value && typeof value === "object") {
|
|
139809
|
+
const out = {};
|
|
139810
|
+
for (const [k102, v22] of Object.entries(value)) {
|
|
139811
|
+
out[k102] = interpolateEnv4(v22, sourcePath, allowMissing);
|
|
139672
139812
|
}
|
|
139673
|
-
|
|
139813
|
+
return out;
|
|
139814
|
+
}
|
|
139815
|
+
return value;
|
|
139674
139816
|
}
|
|
139675
139817
|
var dynamicImport4;
|
|
139676
139818
|
var FilesystemStorage4;
|
|
@@ -139733,13 +139875,22 @@ checkpoints/*.yaml
|
|
|
139733
139875
|
/* Project Configuration */
|
|
139734
139876
|
/* ────────────────────────────────────────────────────────────── */
|
|
139735
139877
|
/**
|
|
139736
|
-
* Read project configuration
|
|
139878
|
+
* Read project configuration.
|
|
139879
|
+
*
|
|
139880
|
+
* `allowMissingEnv` skips throwing on unset ${VAR} placeholders — used by
|
|
139881
|
+
* `--dry` and `converge doctor`, which validate config shape without
|
|
139882
|
+
* requiring credentials.
|
|
139737
139883
|
*/
|
|
139738
|
-
readProject() {
|
|
139884
|
+
readProject(opts = {}) {
|
|
139739
139885
|
const content = readFileSync(this.paths.project, "utf8");
|
|
139740
|
-
const
|
|
139741
|
-
const
|
|
139742
|
-
|
|
139886
|
+
const parsed = parse(content);
|
|
139887
|
+
const allowMissing = opts.allowMissingEnv ?? process.env.CONVERGE_ALLOW_MISSING_ENV === "1";
|
|
139888
|
+
const interpolated = interpolateEnv4(
|
|
139889
|
+
parsed,
|
|
139890
|
+
this.paths.project,
|
|
139891
|
+
allowMissing
|
|
139892
|
+
);
|
|
139893
|
+
return ProjectConfigSchema4.parse(interpolated);
|
|
139743
139894
|
}
|
|
139744
139895
|
/**
|
|
139745
139896
|
* Write project configuration
|
|
@@ -140055,7 +140206,7 @@ ${message}
|
|
|
140055
140206
|
};
|
|
140056
140207
|
}
|
|
140057
140208
|
});
|
|
140058
|
-
async function loadProjectMdConfig3(configPath) {
|
|
140209
|
+
async function loadProjectMdConfig3(configPath, opts = {}) {
|
|
140059
140210
|
let raw;
|
|
140060
140211
|
try {
|
|
140061
140212
|
raw = await readFile(configPath, "utf-8");
|
|
@@ -140085,11 +140236,16 @@ See PROJECT.md format reference.`
|
|
|
140085
140236
|
See PROJECT.md format reference.`
|
|
140086
140237
|
);
|
|
140087
140238
|
}
|
|
140239
|
+
frontmatter = substituteEnvVarsInTree3(
|
|
140240
|
+
frontmatter,
|
|
140241
|
+
configPath,
|
|
140242
|
+
opts.allowMissingEnv ?? false
|
|
140243
|
+
);
|
|
140088
140244
|
const body = raw.slice(match2[0].length).trim();
|
|
140089
140245
|
const projectDir = dirname(dirname(configPath));
|
|
140090
140246
|
return buildConfigFromData3(frontmatter, projectDir, body);
|
|
140091
140247
|
}
|
|
140092
|
-
async function loadProjectYamlConfig3(configPath) {
|
|
140248
|
+
async function loadProjectYamlConfig3(configPath, opts = {}) {
|
|
140093
140249
|
let raw;
|
|
140094
140250
|
try {
|
|
140095
140251
|
raw = await readFile(configPath, "utf-8");
|
|
@@ -140099,18 +140255,6 @@ async function loadProjectYamlConfig3(configPath) {
|
|
|
140099
140255
|
${err.message}`
|
|
140100
140256
|
);
|
|
140101
140257
|
}
|
|
140102
|
-
raw = raw.replace(
|
|
140103
|
-
/\$(\$)|\$\{([A-Z0-9_]+)(?::-([^}]*))?\}/g,
|
|
140104
|
-
(_m, dollar, name, fallback) => {
|
|
140105
|
-
if (dollar) return "$";
|
|
140106
|
-
const value = process.env[name];
|
|
140107
|
-
if (value !== void 0) return value;
|
|
140108
|
-
if (fallback !== void 0) return fallback;
|
|
140109
|
-
throw new Error(
|
|
140110
|
-
`${configPath}: ${name} is not set. Add it to .env.local or export it before running the CLI.`
|
|
140111
|
-
);
|
|
140112
|
-
}
|
|
140113
|
-
);
|
|
140114
140258
|
let data;
|
|
140115
140259
|
try {
|
|
140116
140260
|
data = parse(raw);
|
|
@@ -140124,9 +140268,44 @@ async function loadProjectYamlConfig3(configPath) {
|
|
|
140124
140268
|
See project.yaml format reference.`
|
|
140125
140269
|
);
|
|
140126
140270
|
}
|
|
140271
|
+
data = substituteEnvVarsInTree3(
|
|
140272
|
+
data,
|
|
140273
|
+
configPath,
|
|
140274
|
+
opts.allowMissingEnv ?? false
|
|
140275
|
+
);
|
|
140127
140276
|
const projectDir = dirname(dirname(configPath));
|
|
140128
140277
|
return buildConfigFromData3(data, projectDir);
|
|
140129
140278
|
}
|
|
140279
|
+
function substituteEnvVarsInTree3(value, configPath, allowMissingEnv) {
|
|
140280
|
+
if (typeof value === "string") {
|
|
140281
|
+
return value.replace(
|
|
140282
|
+
/\$(\$)|\$\{([A-Z0-9_]+)(?::-([^}]*))?\}/g,
|
|
140283
|
+
(_m, dollar, name, fallback) => {
|
|
140284
|
+
if (dollar) return "$";
|
|
140285
|
+
const envValue = process.env[name];
|
|
140286
|
+
if (envValue !== void 0) return envValue;
|
|
140287
|
+
if (fallback !== void 0) return fallback;
|
|
140288
|
+
if (allowMissingEnv) return "";
|
|
140289
|
+
throw new Error(
|
|
140290
|
+
`${configPath}: ${name} is not set. Add it to .env.local or export it before running the CLI.`
|
|
140291
|
+
);
|
|
140292
|
+
}
|
|
140293
|
+
);
|
|
140294
|
+
}
|
|
140295
|
+
if (Array.isArray(value)) {
|
|
140296
|
+
return value.map(
|
|
140297
|
+
(v22) => substituteEnvVarsInTree3(v22, configPath, allowMissingEnv)
|
|
140298
|
+
);
|
|
140299
|
+
}
|
|
140300
|
+
if (value && typeof value === "object") {
|
|
140301
|
+
const out = {};
|
|
140302
|
+
for (const [k102, v22] of Object.entries(value)) {
|
|
140303
|
+
out[k102] = substituteEnvVarsInTree3(v22, configPath, allowMissingEnv);
|
|
140304
|
+
}
|
|
140305
|
+
return out;
|
|
140306
|
+
}
|
|
140307
|
+
return value;
|
|
140308
|
+
}
|
|
140130
140309
|
function buildConfigFromData3(data, projectDir, body) {
|
|
140131
140310
|
const config = {
|
|
140132
140311
|
name: data.name,
|
|
@@ -140153,12 +140332,12 @@ function buildConfigFromData3(data, projectDir, body) {
|
|
|
140153
140332
|
}
|
|
140154
140333
|
return config;
|
|
140155
140334
|
}
|
|
140156
|
-
async function loadConvergeConfig3(configPath, type2) {
|
|
140335
|
+
async function loadConvergeConfig3(configPath, type2, opts = {}) {
|
|
140157
140336
|
const configType = configPath.endsWith("project.yaml") || configPath.endsWith("project.yml") ? "project.yaml" : "PROJECT.md";
|
|
140158
140337
|
if (configType === "project.yaml") {
|
|
140159
|
-
return loadProjectYamlConfig3(configPath);
|
|
140338
|
+
return loadProjectYamlConfig3(configPath, opts);
|
|
140160
140339
|
} else {
|
|
140161
|
-
return loadProjectMdConfig3(configPath);
|
|
140340
|
+
return loadProjectMdConfig3(configPath, opts);
|
|
140162
140341
|
}
|
|
140163
140342
|
}
|
|
140164
140343
|
function convertScriptHooks3(hooks, projectDir) {
|
|
@@ -158632,7 +158811,7 @@ async function findConvergeConfig2(startDir) {
|
|
|
158632
158811
|
}
|
|
158633
158812
|
}
|
|
158634
158813
|
var FRONTMATTER_RE4 = /^---\r?\n([\s\S]*?)\r?\n---/;
|
|
158635
|
-
async function loadProjectMdConfig4(configPath) {
|
|
158814
|
+
async function loadProjectMdConfig4(configPath, opts = {}) {
|
|
158636
158815
|
let raw;
|
|
158637
158816
|
try {
|
|
158638
158817
|
raw = await readFile(configPath, "utf-8");
|
|
@@ -158662,11 +158841,16 @@ See PROJECT.md format reference.`
|
|
|
158662
158841
|
See PROJECT.md format reference.`
|
|
158663
158842
|
);
|
|
158664
158843
|
}
|
|
158844
|
+
frontmatter = substituteEnvVarsInTree4(
|
|
158845
|
+
frontmatter,
|
|
158846
|
+
configPath,
|
|
158847
|
+
opts.allowMissingEnv ?? false
|
|
158848
|
+
);
|
|
158665
158849
|
const body = raw.slice(match2[0].length).trim();
|
|
158666
158850
|
const projectDir = dirname(dirname(configPath));
|
|
158667
158851
|
return buildConfigFromData4(frontmatter, projectDir, body);
|
|
158668
158852
|
}
|
|
158669
|
-
async function loadProjectYamlConfig4(configPath) {
|
|
158853
|
+
async function loadProjectYamlConfig4(configPath, opts = {}) {
|
|
158670
158854
|
let raw;
|
|
158671
158855
|
try {
|
|
158672
158856
|
raw = await readFile(configPath, "utf-8");
|
|
@@ -158676,18 +158860,6 @@ async function loadProjectYamlConfig4(configPath) {
|
|
|
158676
158860
|
${err.message}`
|
|
158677
158861
|
);
|
|
158678
158862
|
}
|
|
158679
|
-
raw = raw.replace(
|
|
158680
|
-
/\$(\$)|\$\{([A-Z0-9_]+)(?::-([^}]*))?\}/g,
|
|
158681
|
-
(_m, dollar, name, fallback) => {
|
|
158682
|
-
if (dollar) return "$";
|
|
158683
|
-
const value = process.env[name];
|
|
158684
|
-
if (value !== void 0) return value;
|
|
158685
|
-
if (fallback !== void 0) return fallback;
|
|
158686
|
-
throw new Error(
|
|
158687
|
-
`${configPath}: ${name} is not set. Add it to .env.local or export it before running the CLI.`
|
|
158688
|
-
);
|
|
158689
|
-
}
|
|
158690
|
-
);
|
|
158691
158863
|
let data;
|
|
158692
158864
|
try {
|
|
158693
158865
|
data = parse(raw);
|
|
@@ -158701,9 +158873,44 @@ async function loadProjectYamlConfig4(configPath) {
|
|
|
158701
158873
|
See project.yaml format reference.`
|
|
158702
158874
|
);
|
|
158703
158875
|
}
|
|
158876
|
+
data = substituteEnvVarsInTree4(
|
|
158877
|
+
data,
|
|
158878
|
+
configPath,
|
|
158879
|
+
opts.allowMissingEnv ?? false
|
|
158880
|
+
);
|
|
158704
158881
|
const projectDir = dirname(dirname(configPath));
|
|
158705
158882
|
return buildConfigFromData4(data, projectDir);
|
|
158706
158883
|
}
|
|
158884
|
+
function substituteEnvVarsInTree4(value, configPath, allowMissingEnv) {
|
|
158885
|
+
if (typeof value === "string") {
|
|
158886
|
+
return value.replace(
|
|
158887
|
+
/\$(\$)|\$\{([A-Z0-9_]+)(?::-([^}]*))?\}/g,
|
|
158888
|
+
(_m, dollar, name, fallback) => {
|
|
158889
|
+
if (dollar) return "$";
|
|
158890
|
+
const envValue = process.env[name];
|
|
158891
|
+
if (envValue !== void 0) return envValue;
|
|
158892
|
+
if (fallback !== void 0) return fallback;
|
|
158893
|
+
if (allowMissingEnv) return "";
|
|
158894
|
+
throw new Error(
|
|
158895
|
+
`${configPath}: ${name} is not set. Add it to .env.local or export it before running the CLI.`
|
|
158896
|
+
);
|
|
158897
|
+
}
|
|
158898
|
+
);
|
|
158899
|
+
}
|
|
158900
|
+
if (Array.isArray(value)) {
|
|
158901
|
+
return value.map(
|
|
158902
|
+
(v22) => substituteEnvVarsInTree4(v22, configPath, allowMissingEnv)
|
|
158903
|
+
);
|
|
158904
|
+
}
|
|
158905
|
+
if (value && typeof value === "object") {
|
|
158906
|
+
const out = {};
|
|
158907
|
+
for (const [k102, v22] of Object.entries(value)) {
|
|
158908
|
+
out[k102] = substituteEnvVarsInTree4(v22, configPath, allowMissingEnv);
|
|
158909
|
+
}
|
|
158910
|
+
return out;
|
|
158911
|
+
}
|
|
158912
|
+
return value;
|
|
158913
|
+
}
|
|
158707
158914
|
function buildConfigFromData4(data, projectDir, body) {
|
|
158708
158915
|
const config = {
|
|
158709
158916
|
name: data.name,
|
|
@@ -158730,12 +158937,12 @@ function buildConfigFromData4(data, projectDir, body) {
|
|
|
158730
158937
|
}
|
|
158731
158938
|
return config;
|
|
158732
158939
|
}
|
|
158733
|
-
async function loadConvergeConfig4(configPath, type2) {
|
|
158940
|
+
async function loadConvergeConfig4(configPath, type2, opts = {}) {
|
|
158734
158941
|
const configType = type2 || (configPath.endsWith("project.yaml") || configPath.endsWith("project.yml") ? "project.yaml" : "PROJECT.md");
|
|
158735
158942
|
if (configType === "project.yaml") {
|
|
158736
|
-
return loadProjectYamlConfig4(configPath);
|
|
158943
|
+
return loadProjectYamlConfig4(configPath, opts);
|
|
158737
158944
|
} else {
|
|
158738
|
-
return loadProjectMdConfig4(configPath);
|
|
158945
|
+
return loadProjectMdConfig4(configPath, opts);
|
|
158739
158946
|
}
|
|
158740
158947
|
}
|
|
158741
158948
|
var HOOK_TIMEOUT_MS4 = 3e4;
|
|
@@ -158793,10 +159000,13 @@ function buildSafePayload4(event, payload) {
|
|
|
158793
159000
|
}
|
|
158794
159001
|
return safe;
|
|
158795
159002
|
}
|
|
158796
|
-
async function resolveConvergeConfig2(startDir) {
|
|
159003
|
+
async function resolveConvergeConfig2(startDir, opts = {}) {
|
|
158797
159004
|
const result = await findConvergeConfig2(startDir);
|
|
158798
159005
|
if (!result) return null;
|
|
158799
|
-
const
|
|
159006
|
+
const effective = {
|
|
159007
|
+
allowMissingEnv: opts.allowMissingEnv ?? process.env.CONVERGE_ALLOW_MISSING_ENV === "1"
|
|
159008
|
+
};
|
|
159009
|
+
const config = await loadConvergeConfig4(result.path, result.type, effective);
|
|
158800
159010
|
return { config, configPath: result.path, type: result.type };
|
|
158801
159011
|
}
|
|
158802
159012
|
init_esm_shims5();
|
|
@@ -191722,8 +191932,26 @@ async function doctorCommand({
|
|
|
191722
191932
|
contradictoryFindings: [],
|
|
191723
191933
|
staleSentinels: [],
|
|
191724
191934
|
trippedCircuits: [],
|
|
191725
|
-
malformedSkills: []
|
|
191935
|
+
malformedSkills: [],
|
|
191936
|
+
configErrors: []
|
|
191726
191937
|
};
|
|
191938
|
+
try {
|
|
191939
|
+
await resolveConvergeConfig2(workspace, { allowMissingEnv: true });
|
|
191940
|
+
} catch (err) {
|
|
191941
|
+
const msg = err?.message ?? String(err);
|
|
191942
|
+
const idx = msg.indexOf(": ");
|
|
191943
|
+
if (idx > 0 && msg.slice(0, idx).includes(".converge/project")) {
|
|
191944
|
+
report.configErrors.push({
|
|
191945
|
+
path: msg.slice(0, idx),
|
|
191946
|
+
reason: msg.slice(idx + 2).trim()
|
|
191947
|
+
});
|
|
191948
|
+
} else {
|
|
191949
|
+
report.configErrors.push({
|
|
191950
|
+
path: join(workspace, ".converge", "project.yaml"),
|
|
191951
|
+
reason: msg
|
|
191952
|
+
});
|
|
191953
|
+
}
|
|
191954
|
+
}
|
|
191727
191955
|
const defGaps = await findDefinitionGaps2(workspace, playbook);
|
|
191728
191956
|
for (const d16 of defGaps) {
|
|
191729
191957
|
report.definitionGaps.push({
|
|
@@ -191807,7 +192035,7 @@ async function doctorCommand({
|
|
|
191807
192035
|
}
|
|
191808
192036
|
}
|
|
191809
192037
|
}
|
|
191810
|
-
const totalFindings = report.definitionGaps.length + report.phantomWorkItems.length + report.contradictoryFindings.length + report.staleSentinels.length + report.trippedCircuits.length + report.malformedSkills.length;
|
|
192038
|
+
const totalFindings = report.definitionGaps.length + report.phantomWorkItems.length + report.contradictoryFindings.length + report.staleSentinels.length + report.trippedCircuits.length + report.malformedSkills.length + report.configErrors.length;
|
|
191811
192039
|
if (jsonOut) {
|
|
191812
192040
|
console.log(
|
|
191813
192041
|
JSON.stringify({ totalFindings, ...report, fixed: fix }, null, 2)
|
|
@@ -191878,6 +192106,17 @@ function printHumanReport(report, total, fixed) {
|
|
|
191878
192106
|
if (fixed) console.log(` (re-armed by --fix)`);
|
|
191879
192107
|
console.log();
|
|
191880
192108
|
}
|
|
192109
|
+
if (report.configErrors.length > 0) {
|
|
192110
|
+
console.log(
|
|
192111
|
+
`\u25CF ${report.configErrors.length} project config error(s) \u2014 .converge/project.yaml will fail to load:`
|
|
192112
|
+
);
|
|
192113
|
+
for (const c of report.configErrors) {
|
|
192114
|
+
console.log(` ${c.path}`);
|
|
192115
|
+
console.log(` reason: ${c.reason.split("\n")[0].slice(0, 200)}`);
|
|
192116
|
+
}
|
|
192117
|
+
console.log(` (--fix does NOT touch project.yaml \u2014 edit it yourself)`);
|
|
192118
|
+
console.log();
|
|
192119
|
+
}
|
|
191881
192120
|
if (report.malformedSkills.length > 0) {
|
|
191882
192121
|
console.log(
|
|
191883
192122
|
`\u25CF ${report.malformedSkills.length} malformed SKILL.md file(s) \u2014 skill directories silently skipped by the catalog loader:`
|
|
@@ -209958,7 +210197,7 @@ function renderProjectYaml(args) {
|
|
|
209958
210197
|
if (args.description) lines.push(`description: ${yamlEscape(args.description)}`);
|
|
209959
210198
|
lines.push("");
|
|
209960
210199
|
lines.push("# AI provider configuration \u2014 one default, multiple enabled.");
|
|
209961
|
-
lines.push("# Replace $
|
|
210200
|
+
lines.push("# Replace $VAR placeholders with real keys or export them in your shell.");
|
|
209962
210201
|
lines.push("ai:");
|
|
209963
210202
|
lines.push(` default: ${args.defaultAgent}`);
|
|
209964
210203
|
lines.push(" providers:");
|
|
@@ -211478,7 +211717,13 @@ async function main() {
|
|
|
211478
211717
|
const localProjectYaml = join(localConvergeDir, "project.yaml");
|
|
211479
211718
|
const localProjectMd = join(localConvergeDir, "PROJECT.md");
|
|
211480
211719
|
const hasLocalProject = existsSync(localProjectYml) || existsSync(localProjectYaml) || existsSync(localProjectMd);
|
|
211481
|
-
|
|
211720
|
+
const isDryRunEarly = !!(options.dry || options.plan);
|
|
211721
|
+
if (isDryRunEarly) {
|
|
211722
|
+
process.env.CONVERGE_ALLOW_MISSING_ENV = "1";
|
|
211723
|
+
}
|
|
211724
|
+
let resolved = await resolveConvergeConfig2(searchDir, {
|
|
211725
|
+
allowMissingEnv: isDryRunEarly
|
|
211726
|
+
});
|
|
211482
211727
|
if (resolved && !hasLocalProject) {
|
|
211483
211728
|
const resolvedDir = dirname(resolved.configPath);
|
|
211484
211729
|
const resolvedIsParent = resolvedDir !== searchDir;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openplaybooks/converge",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "CLI for Converge - A build system for AI agents",
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
"@clack/prompts": "^0.9.1",
|
|
34
34
|
"glob": "^13.0.0",
|
|
35
35
|
"yaml": "^2.8.3",
|
|
36
|
+
"@openplaybooks/codexfn": "0.1.0",
|
|
37
|
+
"@openplaybooks/openfn": "^0.1.0",
|
|
38
|
+
"@openplaybooks/converge-core": "0.2.3",
|
|
36
39
|
"@openplaybooks/agentfn": "0.2.1",
|
|
37
|
-
"@openplaybooks/converge-core": "0.2.2",
|
|
38
40
|
"@openplaybooks/deepcodefn": "0.1.0",
|
|
39
|
-
"@openplaybooks/
|
|
40
|
-
"@openplaybooks/claudefn": "0.1.0",
|
|
41
|
-
"@openplaybooks/codexfn": "0.1.0"
|
|
41
|
+
"@openplaybooks/claudefn": "0.1.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "^22.0.0",
|