valent-pipeline 0.19.29 → 0.19.30

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valent-pipeline",
3
- "version": "0.19.29",
3
+ "version": "0.19.30",
4
4
  "description": "v3 multi-agent AI pipeline for software development lifecycle",
5
5
  "type": "module",
6
6
  "bin": {
Binary file
package/src/lib/sprint.js CHANGED
@@ -154,14 +154,21 @@ export function packSprint(stories, velocity, opts = {}) {
154
154
  const groomed = stories.filter((s) => (!scope || scope.has(s.id)) && isExecReady(s) && bugsResolvable(s));
155
155
  const byId = new Map(groomed.map((s) => [s.id, s]));
156
156
 
157
- // Out-of-batch prerequisite check (review 2026-06-10 #20): a depends_on that is not packable
158
- // this sprint clears only if it already landed (or is absent from the file — pre-backlog work);
159
- // a pending/stranded/blocked prerequisite withholds the dependent.
160
- const outOfBatchDepsSatisfied = (story) => depsOf(story).every((depId) => {
161
- if (byId.has(depId)) return true; // packable this sprint sequenced before the story below
162
- const known = byIdAll.get(depId);
163
- return !known || satisfied.has(known.status);
164
- });
157
+ // Out-of-batch prerequisite check (review 2026-06-10 #20), now TRANSITIVE (HARNESS-GAPS 2026-06-18
158
+ // Gap 3): a depends_on clears only if it already landed (or is absent — pre-backlog work), OR is
159
+ // packable this sprint AND its OWN dependency chain likewise clears. Checking only DIRECT deps let
160
+ // an in-sprint dep whose prerequisite is unshipped slip in as a velocity-filler, building against
161
+ // unbuilt code `resolveEligibleStories` already requires the WHOLE chain to be live; the packer
162
+ // must agree or the two disagree about what runs.
163
+ const outOfBatchDepsSatisfied = (story, seen = new Set()) => {
164
+ if (seen.has(story.id)) return true; // cycle guard — a dependency cycle is a backlog error, not the packer's to resolve
165
+ seen.add(story.id);
166
+ return depsOf(story).every((depId) => {
167
+ if (byId.has(depId)) return outOfBatchDepsSatisfied(byId.get(depId), seen); // in-sprint dep — its chain must hold too
168
+ const known = byIdAll.get(depId);
169
+ return !known || satisfied.has(known.status);
170
+ });
171
+ };
165
172
 
166
173
  const byPriority = [...groomed].sort(
167
174
  (a, b) => (a.priority ?? Infinity) - (b.priority ?? Infinity),