Add fire-and-forget mirror push support so merges to the primary branch
are automatically pushed to configured public mirrors (GitHub, Codeberg,
etc.). Mirror failures are logged but never block the pipeline.
- lib/mirrors.sh: new shared mirror_push() helper
- lib/load-project.sh: parse [mirrors] TOML section into MIRROR_* env vars
- dev/phase-handler.sh: call mirror_push after do_merge() success
- dev/dev-poll.sh: call mirror_push after try_direct_merge() success
- gardener/gardener-run.sh: call mirror_push after _gardener_merge() success
- bin/disinto: set up mirror remotes during init, add commented mirrors to
generated TOML
- projects/*.toml.example: show [mirrors] section (commented out)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Warn on stderr when .env.enc decryption fails instead of silent || true
- Guard ensure_age_key() against empty age-keygen -y output
- Fix stale comment on write_secrets_encrypted()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add ci_commit_status() and ci_pipeline_number() helpers to
lib/ci-helpers.sh that query Woodpecker directly with a forge API
fallback. Replace all 12 inline forge commit status calls across 6
files with the new helpers.
Add setup_woodpecker() to bin/disinto init that creates a Forgejo
OAuth2 app for Woodpecker and activates the repo.
Document manual Woodpecker+Forgejo setup in BOOTSTRAP.md.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a re-evaluate-backlog step to the predictor formula between
collect-signals and analyze-and-predict. For each open prediction/backlog
issue, the predictor now reads the original context and planner comments,
extracts the assumptions that made it "watch, don't act", and re-checks
those conditions against current system state.
Three outcomes:
- CONDITIONS_CHANGED → file new prediction/unreviewed, close old as superseded
- STALE (30+ days, conditions stable) → close as prediction/actioned
- UNCHANGED_RECENT → skip (existing behavior)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When Claude finishes a response but hasn't written to the PHASE file,
the stop hook now injects a nudge into the tmux session instead of just
marking idle. This gives Claude another chance to complete the phase
protocol before the monitor loop times out.
Key changes:
- on-idle-stop.sh: check phase file emptiness, nudge via tmux (max 2)
- agent-session.sh: pass phase_file + session to stop hook, clean up
nudge counter on session teardown
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename the CTA link from 'Watch it work' to 'See active issues' so
visitors know the link leads to the issue tracker, not a demo or live view.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Source the canonical read_phase() from lib/agent-session.sh instead of
maintaining a local copy that could drift.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The BACKLOG_NUMS associative array was built to track which issue numbers
are in the backlog, but the DFS cycle-detection code used NODE_COLOR as
a membership guard instead. This meant deps pointing to non-backlog issues
were only skipped by coincidence (they weren't in NODE_COLOR either).
Three changes:
- Remove SC2034 suppression since BACKLOG_NUMS is now actually queried
- Initialize NODE_COLOR from BACKLOG_NUMS keys (all backlog issues) instead
of DEPS_OF keys (only issues with dependencies), so every backlog issue
gets a proper DFS color
- Replace the NODE_COLOR membership check with BACKLOG_NUMS in the DFS, so
the guard explicitly asks "is this dep a backlog issue?" rather than
relying on NODE_COLOR initialization as a proxy
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pipeline #936 (same commit) passed all steps. #935 agent-smoke
failed intermittently on BusyBox awk function resolution.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: two code paths injected merge curl commands into Claude's
session (review-poll.sh APPROVE injection and dev-agent.sh prompt
instructions). The PreToolUse guard correctly blocked these, causing
Claude to write PHASE:escalate instead of merging.
The bash phase handler already handles merging via do_merge() — which
runs outside Claude tool use and is not subject to the guard. Remove
the merge/close curl instructions from both Claude-facing prompts so
the bash orchestrator handles merges as intended.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>