goalChangeRef returned the full GoalSnapshot for every snapshot operation,
so foldGoal(...).lastRef and the goal/changed notification ref carried
objective, phase, and maxGoalRounds fields instead of the declared
GoalRef { id, revision }. Only the clear tombstone was bare. Emit an exact
{ id, revision } ref for snapshot changes and pin the contract with a
regression test covering create/edit/block notifications and the fold.
CI caught a startup race the PTY smoke stages naturally: a TUI /exit typed
while watchPersonalPatches is still opening its watcher disposes the tree,
and the HMR effect registration rejects with INACTIVE_EFFECT, crashing an
app that exited exactly as asked. Return a no-op disposer for that exact
code; every other registration failure still propagates (covered both ways).
ds-review-bot round 1 on the DSH-home integration:
- generated wrappers now inject the services their manifest needs (skills/
tools beside loader), and loadPreparedRepository rejects a wrapper fiber
that settles anything but ACTIVE — a composition missing a required
service fails the repository transaction instead of committing an ACTIVE
row over a silently PENDING child (critical finding)
- the github: source ref segment excludes '#', so 'a#b' refs fail at the
config parser with the promised syntax instead of inside pnpm
- watchPersonalPatches re-reads the include's non-patch options per refresh
instead of a registration-time snapshot
- the TUI smoke's cache-seeded wrapper is produced by the real
prepareDshPlugin (cache LAYOUT stays a deliberate external pin)
- new Loader integration test drives a live repositories update through
entry.update: generation swap, old skills removed, failed candidate
rolled back to the previous generation
ds-review-bot round 1 on the repository-plugin runtime:
- a manifest-declared skill root absent or non-directory in the installed
package now fails the plugin load (skill-local treats a missing root as
legitimately empty, which silently mounted a skill-less plugin)
- includeDefaultRoots: false no longer inherits $DSH_BUNDLED_SKILL_DIR, so
isolated repository providers see only their explicit roots
- prepared wrapper baseUrl schema requires the file: scheme, failing hostile
URLs at the declared validation boundary
- preparedPath reuses format.ts's isOutside; SERVER_NAME_PATTERN is exported
and pinned equal to dsh-mcp-client's, with the restatement justified (the
prepare bin keeps a zod-only module graph); the unexplained `as never`
cast now carries its schemastery rationale
- the import-free wrapper assertion also rejects dynamic import(
- the headless fixture wrapper is regenerated by the real prepareDshPlugin
and a drift test pins fixture == generator output
- prepareDshPlugin JSDoc states the non-atomic publish repair contract
ds-review-bot round 1: boot() now throws `host preparation failed` when
prepare() rejects before any config-tree entry mounts (the plugin-tree label
overstated), and the new hygiene gate verify-vendored-links pins the
linkWorkspacePackages fix — every vendored package name in pnpm-lock.yaml
must resolve to a workspace link with no registry copy alongside.