@bvdm/delano 0.2.6 → 0.2.7

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/README.md CHANGED
@@ -15,7 +15,7 @@ The npm package is intentionally thin. It distributes the approved runtime paylo
15
15
  ## Delano CLI
16
16
 
17
17
  - Package: `@bvdm/delano`
18
- - Current package version: `0.2.4`
18
+ - Current package version: `0.2.7`
19
19
  - Binary: `delano`
20
20
  - Commands: `onboarding`, `install`, `viewer`, `init`, `validate`, `status`, `next`
21
21
  - Primary goal: bootstrap a repo safely, expose local delivery state clearly, and keep runtime gates verifiable
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bvdm/delano",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "description": "CLI for the Delano delivery runtime.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -472,12 +472,56 @@ function applyTaskRollups({ project, task, action, previousStatus, timestamp, ch
472
472
  promoteWorkstreamToActive(project, workstream, timestamp, changes);
473
473
  }
474
474
 
475
+ if (action === "close") {
476
+ openDependencyReadyTasks(project, task, timestamp, changes);
477
+ }
478
+
475
479
  if (["close", "defer"].includes(action)) {
476
480
  closeWorkstreamIfDone(project, workstream, timestamp, changes);
477
481
  closeProjectIfDone(project, timestamp, changes);
478
482
  }
479
483
  }
480
484
 
485
+ function openDependencyReadyTasks(project, completedTask, timestamp, changes) {
486
+ const completedTaskId = String(completedTask.frontmatter.id || "").trim();
487
+ if (!completedTaskId) {
488
+ return;
489
+ }
490
+
491
+ for (const candidate of project.tasks) {
492
+ if (candidate === completedTask || !isDependencyOnlyBlockedTask(project, candidate, completedTaskId)) {
493
+ continue;
494
+ }
495
+
496
+ setFrontmatter(candidate, "status", "ready");
497
+ setFrontmatter(candidate, "updated", timestamp);
498
+ removeFrontmatter(candidate, "blocked_owner");
499
+ removeFrontmatter(candidate, "blocked_check_back");
500
+ appendEvidence(candidate, timestamp, `Opened automatically because dependencies are done after ${completedTaskId} closed.`);
501
+ changes.push(`${relativeProjectPath(project, candidate.path)} status -> ready`);
502
+ }
503
+ }
504
+
505
+ function isDependencyOnlyBlockedTask(project, task, completedTaskId) {
506
+ if ((task.frontmatter.status || "") !== "blocked") {
507
+ return false;
508
+ }
509
+
510
+ const dependencies = parseInlineList(task.frontmatter.depends_on || "[]");
511
+ if (!dependencies.includes(completedTaskId)) {
512
+ return false;
513
+ }
514
+ if (!dependencies.every((dependencyId) => findTask(project, dependencyId)?.frontmatter.status === "done")) {
515
+ return false;
516
+ }
517
+
518
+ const owner = String(task.frontmatter.blocked_owner || "").trim().toLowerCase();
519
+ if (!owner) {
520
+ return true;
521
+ }
522
+ return ["dependency", "dependencies", "delano", "delano-cli", "system", "auto", "automation"].includes(owner);
523
+ }
524
+
481
525
  function assertTaskWorkstreamExists(project, task, action) {
482
526
  const workstreamId = String(task.frontmatter.workstream || "").trim();
483
527
  if (!workstreamId) {