vinta-ai-workflows 0.7.0-alpha17 → 0.7.0-alpha18

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.
Files changed (2) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,7 @@ the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
  ## [0.7.0] — YYYY-MM-DD
9
9
 
10
+ <!-- pre-release: 0.7.0-alpha18 on 2026-09-17 -->
10
11
  <!-- pre-release: 0.7.0-alpha17 on 2026-09-17 -->
11
12
  <!-- pre-release: 0.7.0-alpha16 on 2026-09-16 -->
12
13
  <!-- pre-release: 0.7.0-alpha15 on 2026-09-16 -->
@@ -547,6 +548,88 @@ the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
547
548
 
548
549
  ### Fixed
549
550
 
551
+ - **A conflict fixer that committed its own resolution failed the phase.** An
552
+ agent told to resolve a merge conflict reaches for the sequence a person
553
+ would — abort, merge again, resolve, commit — and the orchestrator then
554
+ committed unconditionally on top of it. Against an already-committed
555
+ resolution `git add --all` is a no-op that exits 0 and `git commit --no-edit`
556
+ exits 1 with "nothing to commit", which is a throw. A successful resolution
557
+ was reported as a failed phase, deterministically, on **every wave after a
558
+ parallel one**: a multi-dependency node is the only thing that merges here,
559
+ and two sibling phases both creating one file is the common case rather than
560
+ the rare one. The phase died before its branch was cut, so it left no
561
+ transcript, no gate log and no branch — only a resolved merge commit sitting
562
+ in the integration worktree. The commit is now conditional on there being
563
+ something to commit, and a fixer that discarded the merge instead of resolving
564
+ it is refused rather than recorded as integrated.
565
+
566
+ - **The conflict fixer's turn is in the transcript now.** Its event stream was
567
+ drained and every event dropped — an unread stream never ends — so the one
568
+ agent turn in a run nobody could watch live was also the one nobody could read
569
+ afterwards: a resolved merge, a row saying it took two rounds, and no record of
570
+ what was decided. It lands in the incoming phase's own transcript, beside the
571
+ implementer and reviewer turns that produced the branches being merged, under
572
+ a `conflict-fixer` role that keeps it distinguishable from the review fixer —
573
+ a different job, in a different worktree, on a different thing. The UI has had
574
+ a band for that role since transcripts learned to name their authors; it had
575
+ simply never been given one to draw.
576
+
577
+ - **`PlanDefectError` is now `UnresolvedConflictError`.** The old name made a
578
+ judgement the orchestrator is not entitled to make. Two same-wave phases
579
+ touching one file is not a broken plan — the plan's file-overlap analysis is a
580
+ guess made before a line was written, and the fixer exists because of it. What
581
+ reaching that error means is narrower: *this* conflict outlasted its rounds and
582
+ needs a person. The message says so, and now leads with finishing the merge by
583
+ hand in the integration worktree — which, since a prepared base is reused,
584
+ survives into the retry — rather than with re-cutting the plan.
585
+
586
+ - **A conflict was resolved again on every retry, and recorded nowhere.**
587
+ Conflicts are an ordinary outcome — the plan's file-overlap analysis is a
588
+ guess and two sibling phases legitimately edit one file — but `prepareBase`
589
+ reset and re-merged its `integ-<id>` branch unconditionally, so each retry
590
+ spawned a fresh fixer agent to redo work already done, and discarded any
591
+ resolution a person had finished by hand in that worktree. One observed run
592
+ paid for the same resolution three times. A base that already integrates every
593
+ dependency's current tip is now kept; one built before a dependency moved is
594
+ still rebuilt, because reuse is about reachability of the tips rather than
595
+ about the branch existing. Every settled conflict is also journalled as a
596
+ `node_conflict` event naming both participants, the paths and the rounds it
597
+ took — previously a wave conflict reached only the post-mortem and a *base*
598
+ conflict was discarded entirely, so a phase could sit in `running` for minutes
599
+ while an agent merged in a worktree nobody could see.
600
+
601
+ - **A failed attempt now says why, wherever it goes next.** The reason was
602
+ computed at the failure site and handed to the path that gives up — which the
603
+ default `onFailure: retry` does not take: it retries automatically, then parks
604
+ on "This phase failed. Try it again?". Both paths dropped the reason, and
605
+ `#offerRetry` carried a comment asserting the opposite. A phase that failed
606
+ three times before any agent ran was undiagnosable after the fact, and the
607
+ only offered action was to repeat it. Every attempt now writes a `node_error`
608
+ event carrying its reason and attempt number, and a `node.attempt_failed`
609
+ record to the daemon log.
610
+
611
+ - **A git command that exited non-zero was persisted as the word "Error".**
612
+ `failureReason` reports an unrecognised error by its name plus a *string*
613
+ `code`, and an `execFile` rejection carries `name: 'Error'` with a *numeric*
614
+ one — so the most common real failure in this package said nothing at all.
615
+ Git failures now carry their subcommand and exit status (`git commit exited
616
+ 1`), which is a command name and an exit code rather than anything §11 keeps
617
+ out of the journal.
618
+
619
+ - **The conflict fixer ran without its worktree's environment.** It was the one
620
+ agent spawn not given `AgentTask.env`, whose own docstring records this exact
621
+ bug class. With the daemon's bare environment its `docker compose` resolved to
622
+ a project named after the directory rather than the isolated one, ignored the
623
+ `compose.publish: []` override that rides in `COMPOSE_FILE`, and published the
624
+ project's fixed ports on the host — colliding with the developer's own stack
625
+ and outliving the run.
626
+
627
+ - **"Retry with <member>" offered the member that had just failed.** The menu
628
+ excluded the member the *plan* named, but a substitution means the member that
629
+ actually ran is someone else — so a phase declared for one tier and covered by
630
+ a higher one offered that higher one as its escalation, and a third of the
631
+ menu did nothing distinguishable from plain retry.
632
+
550
633
  - **Closing a terminal on a run now records the interruption.** `run` and
551
634
  `serve` handle SIGHUP as well as SIGINT and SIGTERM — SIGHUP is what a
552
635
  terminal sends when its window closes, and with no handler Node's default was
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vinta-ai-workflows",
3
- "version": "0.7.0-alpha17",
3
+ "version": "0.7.0-alpha18",
4
4
  "description": "Bootstrap AI tooling (AGENTS.md, skills, sub-agents) across Claude Code, Codex, Cursor, and VS Code + GitHub Copilot.",
5
5
  "type": "module",
6
6
  "bin": {