poe-code 3.0.361 → 3.0.362
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/index.js +74 -17
- package/dist/index.js.map +3 -3
- package/dist/metafile.json +1 -1
- package/dist/providers/poe-agent.js.map +1 -1
- package/package.json +1 -1
- package/packages/agent-harness-tools/dist/runner.js +4 -1
- package/packages/package-lint/dist/rules/no-published-to-private-dep.js +54 -1
- package/packages/package-lint/dist/rules/published-dep-needs-version-range.js +20 -2
- package/packages/ralph/dist/frontmatter/frontmatter.js +54 -12
- package/packages/ralph/dist/run/ralph.js +1 -1
package/package.json
CHANGED
|
@@ -230,7 +230,7 @@ export async function runDocumentWorkflow(options) {
|
|
|
230
230
|
return;
|
|
231
231
|
}
|
|
232
232
|
let shouldStop = false;
|
|
233
|
-
for (let iteration = 0
|
|
233
|
+
for (let iteration = 0;; iteration += 1) {
|
|
234
234
|
throwIfAborted(options.signal);
|
|
235
235
|
currentWorkflow = iteration === 0 ? initialWorkflow : await readWorkflow();
|
|
236
236
|
if (iteration >= currentWorkflow.maxIterations) {
|
|
@@ -266,6 +266,9 @@ export async function runDocumentWorkflow(options) {
|
|
|
266
266
|
if (shouldStop) {
|
|
267
267
|
break;
|
|
268
268
|
}
|
|
269
|
+
if (iteration + 1 >= currentWorkflow.maxIterations) {
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
269
272
|
}
|
|
270
273
|
}
|
|
271
274
|
catch (error) {
|
|
@@ -15,9 +15,20 @@ export const noPublishedToPrivateDep = {
|
|
|
15
15
|
continue;
|
|
16
16
|
for (const edge of dependencyEdges(consumer)) {
|
|
17
17
|
const dep = model.byName.get(edge.name);
|
|
18
|
-
if (!dep
|
|
18
|
+
if (!dep)
|
|
19
19
|
continue;
|
|
20
20
|
if (edge.field !== "peerDependencies" && consumer.bundledDependencies.includes(dep.name)) {
|
|
21
|
+
violations.push(...collectBundledPrivateDependencyViolations({
|
|
22
|
+
consumer,
|
|
23
|
+
bundledRoot: dep,
|
|
24
|
+
modelByName: model.byName,
|
|
25
|
+
consumerBundled: new Set(consumer.bundledDependencies),
|
|
26
|
+
via: [dep.name]
|
|
27
|
+
}));
|
|
28
|
+
if (dep.private)
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (!dep.private) {
|
|
21
32
|
continue;
|
|
22
33
|
}
|
|
23
34
|
violations.push({
|
|
@@ -34,3 +45,45 @@ export const noPublishedToPrivateDep = {
|
|
|
34
45
|
return violations;
|
|
35
46
|
}
|
|
36
47
|
};
|
|
48
|
+
function collectBundledPrivateDependencyViolations(options) {
|
|
49
|
+
const violations = [];
|
|
50
|
+
const visited = new Set();
|
|
51
|
+
const pending = [
|
|
52
|
+
{ pkg: options.bundledRoot, via: options.via }
|
|
53
|
+
];
|
|
54
|
+
while (pending.length > 0) {
|
|
55
|
+
const current = pending.shift();
|
|
56
|
+
if (visited.has(current.pkg.name)) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
visited.add(current.pkg.name);
|
|
60
|
+
for (const edge of dependencyEdges(current.pkg)) {
|
|
61
|
+
const dep = options.modelByName.get(edge.name);
|
|
62
|
+
if (!dep || !dep.private) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (isBundledRuntimeEdge(current.pkg, edge, dep, options.consumerBundled)) {
|
|
66
|
+
pending.push({ pkg: dep, via: [...current.via, dep.name] });
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
violations.push({
|
|
70
|
+
rule: id,
|
|
71
|
+
package: options.consumer.name,
|
|
72
|
+
severity: "error",
|
|
73
|
+
via: edge.field,
|
|
74
|
+
detail: {
|
|
75
|
+
dependency: dep.name,
|
|
76
|
+
field: edge.field,
|
|
77
|
+
bundledVia: current.via
|
|
78
|
+
},
|
|
79
|
+
message: `published package bundles ${current.via.join(" -> ")}, whose ${edge.field} requires private workspace package ${dep.name}`,
|
|
80
|
+
fix: `Bundle ${dep.name} into ${current.pkg.name}, publish ${dep.name}, or remove the ${edge.field} edge from the bundled package manifest.`
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return violations;
|
|
85
|
+
}
|
|
86
|
+
function isBundledRuntimeEdge(pkg, edge, dep, consumerBundled) {
|
|
87
|
+
return (edge.field !== "peerDependencies" &&
|
|
88
|
+
(pkg.bundledDependencies.includes(dep.name) || consumerBundled.has(dep.name)));
|
|
89
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import semver from "semver";
|
|
1
2
|
import { allPackages, dependencyEdges, isPublishedNpm } from "../model.js";
|
|
2
3
|
const id = "published-dep-needs-version-range";
|
|
3
4
|
/** A `*` / `workspace:*`-style range that does not pin to a bounded set of versions. */
|
|
@@ -36,13 +37,30 @@ export const publishedDepNeedsVersionRange = {
|
|
|
36
37
|
const dep = model.byName.get(edge.name);
|
|
37
38
|
if (!dep || !isPublishedNpm(dep))
|
|
38
39
|
continue;
|
|
39
|
-
if (!isLooseRange(edge.spec))
|
|
40
|
-
continue;
|
|
41
40
|
if (edge.field !== "peerDependencies" && consumer.bundledDependencies.includes(dep.name)) {
|
|
42
41
|
continue;
|
|
43
42
|
}
|
|
43
|
+
if (!isLooseRange(edge.spec) && !semver.satisfies(dep.version, edge.spec)) {
|
|
44
|
+
violations.push({
|
|
45
|
+
rule: id,
|
|
46
|
+
package: consumer.name,
|
|
47
|
+
severity: "error",
|
|
48
|
+
via: edge.field,
|
|
49
|
+
detail: {
|
|
50
|
+
dependency: dep.name,
|
|
51
|
+
field: edge.field,
|
|
52
|
+
range: edge.spec,
|
|
53
|
+
version: dep.version
|
|
54
|
+
},
|
|
55
|
+
message: `published dependency ${dep.name}@${edge.spec} does not include workspace version ${dep.version}`,
|
|
56
|
+
fix: `Replace "${edge.spec}" with a concrete range that includes ${dep.version}, such as "^${dep.version}".`
|
|
57
|
+
});
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
44
60
|
if (isDeclaredLockstepDependency(model, consumer.dir, dep.dir))
|
|
45
61
|
continue;
|
|
62
|
+
if (!isLooseRange(edge.spec))
|
|
63
|
+
continue;
|
|
46
64
|
violations.push({
|
|
47
65
|
rule: id,
|
|
48
66
|
package: consumer.name,
|
|
@@ -146,17 +146,18 @@ export function parseFrontmatterData(value) {
|
|
|
146
146
|
throw new Error('Invalid Ralph frontmatter: "kind" must be "ralph".');
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
|
-
const
|
|
150
|
-
const
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
parseNonNegativeInteger(parsed ? getOwnEntry(parsed, "iteration") : undefined) ??
|
|
156
|
-
defaults.status.iteration;
|
|
157
|
-
const agent = parseAgent(parsed ? getOwnEntry(parsed, "agent") : undefined);
|
|
149
|
+
const { state, iteration } = parseStatusFields(parsed, defaults.status);
|
|
150
|
+
const agentValue = parsed ? getOwnEntry(parsed, "agent") : undefined;
|
|
151
|
+
const agent = parseAgent(agentValue);
|
|
152
|
+
if (parsed !== undefined && hasOwnEntry(parsed, "agent") && agent === undefined) {
|
|
153
|
+
throw new Error('Invalid Ralph frontmatter: "agent" must be a non-empty string or non-empty string array.');
|
|
154
|
+
}
|
|
158
155
|
const extendsValue = parseBoolean(parsed ? getOwnEntry(parsed, "extends") : undefined);
|
|
159
|
-
const
|
|
156
|
+
const iterationsValue = parsed ? getOwnEntry(parsed, "iterations") : undefined;
|
|
157
|
+
const iterations = parsePositiveInteger(iterationsValue);
|
|
158
|
+
if (parsed !== undefined && hasOwnEntry(parsed, "iterations") && iterations === undefined) {
|
|
159
|
+
throw new Error('Invalid Ralph frontmatter: "iterations" must be a positive integer.');
|
|
160
|
+
}
|
|
160
161
|
const skills = parseSkills(parsed ? getOwnEntry(parsed, "skills") : undefined);
|
|
161
162
|
const hooks = parseHooks(parsed ? getOwnEntry(parsed, "hooks") : undefined);
|
|
162
163
|
return {
|
|
@@ -171,6 +172,44 @@ export function parseFrontmatterData(value) {
|
|
|
171
172
|
}
|
|
172
173
|
};
|
|
173
174
|
}
|
|
175
|
+
function parseStatusFields(parsed, defaults) {
|
|
176
|
+
if (parsed === undefined) {
|
|
177
|
+
return defaults;
|
|
178
|
+
}
|
|
179
|
+
const statusValue = getOwnEntry(parsed, "status");
|
|
180
|
+
const legacyIterationValue = getOwnEntry(parsed, "iteration");
|
|
181
|
+
const hasStatus = hasOwnEntry(parsed, "status");
|
|
182
|
+
const hasLegacyIteration = hasOwnEntry(parsed, "iteration");
|
|
183
|
+
const parsedStatus = isRecord(statusValue) ? statusValue : undefined;
|
|
184
|
+
if (hasLegacyIteration && parseNonNegativeInteger(legacyIterationValue) === undefined) {
|
|
185
|
+
throw new Error('Invalid Ralph frontmatter: "iteration" must be a non-negative integer.');
|
|
186
|
+
}
|
|
187
|
+
if (parsedStatus !== undefined) {
|
|
188
|
+
rejectUnknownKeys(parsedStatus, ["state", "iteration"], "status");
|
|
189
|
+
const statusStateValue = getOwnEntry(parsedStatus, "state");
|
|
190
|
+
const statusIterationValue = getOwnEntry(parsedStatus, "iteration");
|
|
191
|
+
const state = parsePlanStatus(statusStateValue);
|
|
192
|
+
const iteration = parseNonNegativeInteger(statusIterationValue);
|
|
193
|
+
if (hasOwnEntry(parsedStatus, "state") && state === undefined) {
|
|
194
|
+
throw new Error('Invalid Ralph frontmatter: "status.state" must be "open", "in_progress", "completed", or "failed".');
|
|
195
|
+
}
|
|
196
|
+
if (hasOwnEntry(parsedStatus, "iteration") && iteration === undefined) {
|
|
197
|
+
throw new Error('Invalid Ralph frontmatter: "status.iteration" must be a non-negative integer.');
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
state: state ?? defaults.state,
|
|
201
|
+
iteration: iteration ?? parseNonNegativeInteger(legacyIterationValue) ?? defaults.iteration
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
const legacyState = parseLegacyStatus(statusValue);
|
|
205
|
+
if (hasStatus && legacyState === undefined) {
|
|
206
|
+
throw new Error('Invalid Ralph frontmatter: "status" must be "open", "pending", "cancelled", "overbake_abort", "in_progress", or "completed".');
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
state: legacyState ?? defaults.state,
|
|
210
|
+
iteration: parseNonNegativeInteger(legacyIterationValue) ?? defaults.iteration
|
|
211
|
+
};
|
|
212
|
+
}
|
|
174
213
|
function parseAgent(value) {
|
|
175
214
|
if (typeof value === "string") {
|
|
176
215
|
const trimmed = value.trim();
|
|
@@ -180,7 +219,7 @@ function parseAgent(value) {
|
|
|
180
219
|
return undefined;
|
|
181
220
|
}
|
|
182
221
|
if (value.length === 0) {
|
|
183
|
-
return
|
|
222
|
+
return undefined;
|
|
184
223
|
}
|
|
185
224
|
const agents = [];
|
|
186
225
|
for (const item of value) {
|
|
@@ -281,6 +320,9 @@ function parseBoolean(value) {
|
|
|
281
320
|
function isRecord(value) {
|
|
282
321
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
283
322
|
}
|
|
323
|
+
function hasOwnEntry(record, key) {
|
|
324
|
+
return Object.prototype.hasOwnProperty.call(record, key);
|
|
325
|
+
}
|
|
284
326
|
function getOwnEntry(record, key) {
|
|
285
|
-
return
|
|
327
|
+
return hasOwnEntry(record, key) ? record[key] : undefined;
|
|
286
328
|
}
|
|
@@ -143,7 +143,7 @@ export async function runRalph(options) {
|
|
|
143
143
|
await updateFrontmatter(fs, absoluteDocPath, "open", iterationsCompleted);
|
|
144
144
|
return;
|
|
145
145
|
}
|
|
146
|
-
if (iterationNumber ===
|
|
146
|
+
if (iterationNumber === currentConfig.maxIterations) {
|
|
147
147
|
await updateFrontmatter(fs, absoluteDocPath, "completed", iterationsCompleted);
|
|
148
148
|
stopReason = "max_iterations";
|
|
149
149
|
return;
|