Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
843cc51
chore(fork): fork release-engineering β€” CI, PATCHES.md manifest, revi…
cwest Jul 1, 2026
54ee32d
feat(webhook): per-route action allow-list with author hard-gate
cwest Jul 1, 2026
14931b7
fix(profiles): count external_dirs skills so dashboard matches CLI
cwest Jul 1, 2026
d0f20ac
feat(discord): make VoiceMixer a discord.AudioSource for voice-channe…
cwest Jul 1, 2026
d2dffff
fix(gateway): retry failed kanban notifications instead of dropping them
cwest Jul 1, 2026
d2069ee
fix(kanban): review tasks bypass dup-PR respawn guards (active_pr/rec…
Jul 1, 2026
3ab9a7f
fix(kanban): subscribe configured report-back target for sessionless …
cwest Jul 1, 2026
1ff7ba3
fix(gateway): run in-process kanban dispatcher on a dedicated executor
cwest Jul 1, 2026
b16b103
fix(kanban): dedup review cards on PR URL in create_task
cwest Jul 1, 2026
638dde7
fix(kanban): measure crash-detect launch grace from current run start
cwest Jul 1, 2026
b5420f3
fix(kanban): reaper clears stale claims on dead workers in non-runnin…
cwest Jul 1, 2026
4b515a8
fix(kanban): restore crashed reviewer to review lane, not build lane
cwest Jul 1, 2026
44f7949
fix(kanban): pin worker git identity to host config at spawn
cwest Jul 1, 2026
e741b78
fix(kanban): active_pr respawn guard honors an explicit unblock
cwest Jul 1, 2026
c94d570
feat(kanban): auto-route review-changes-requested block back to author
cwest Jul 1, 2026
9ce3420
fix(kanban): never spawn a tool-less worker; bound per-tick spawn burst
cwest Jul 1, 2026
d79d702
feat(kanban): wake orchestrator on a transition via loopback webhook …
cwest Jul 1, 2026
94d1076
docs(patches): bump base to main@9be292f1e; drop max-iterations (#19)
cwest Jul 1, 2026
e15393b
πŸ”§ ci(fork): track upstream main HEAD β€” SHA-based scan base + demi aut…
cwest Jul 1, 2026
1520500
✨ feat(kanban): notify on every card transition, never silent (#25)
cwest Jul 1, 2026
7f29695
✨ feat(kanban): wake origin thread session on every transition (#26)
cwest Jul 1, 2026
a270518
πŸ› fix(kanban): decouple transition wake-emit from the chat-ping filte…
cwest Jul 1, 2026
c5b1f1f
πŸ› fix(kanban): resume orchestrator as a distinct turn on a busy-sessi…
cwest Jul 1, 2026
d12ff0a
πŸ› fix(kanban): self-announce transition wake with a unique greppable …
cwest Jul 1, 2026
072f536
⚑️ perf(kanban): cut notifier tick to near-real-time so transitions e…
cwest Jul 1, 2026
7b2ef0e
πŸ› fix(kanban): dispatch a busy-session transition wake as its own tur…
cwest Jul 1, 2026
1b15e81
πŸ› fix(gateway): never suppress a transition-wake turn as a stale repl…
cwest Jul 1, 2026
51ab0ef
fix(gateway): dispatch origin-routed wake on the owning platform adap…
cwest Jul 2, 2026
6f196eb
fix(gateway): exempt system events from the busy-path auth gate (#35)
cwest Jul 2, 2026
fac4252
πŸ› fix(gateway): re-read transition_emit config per notifier tick (#36)
cwest Jul 2, 2026
0a40ba7
πŸ“ docs(webhook): document the concrete origin thread key-mirror invar…
cwest Jul 2, 2026
7f5966b
πŸ› fix(webhook): surface wake-dispatch task exceptions instead of swal…
cwest Jul 2, 2026
799b638
✨ feat(kanban): distinct "ready for you" ping when a card enters the …
cwest Jul 2, 2026
04b531a
πŸ› fix(kanban): atomic PASSβ†’acceptance β€” reconcile stray review/owner …
cwest Jul 2, 2026
467dca3
πŸ› fix(gateway): exempt kanban-transition wakes from the cold-path aut…
cwest Jul 2, 2026
8ff3822
✨ feat(kanban): opt-in allowed_boards guard on create_board (#43)
cwest Jul 2, 2026
41bb1d9
πŸ› fix(kanban): make move_card->blocked a sticky block so acceptance c…
cwest Jul 2, 2026
a4957e0
πŸ› fix(kanban): refuse complete_task on an acceptance-lane card (#45)
cwest Jul 2, 2026
4390416
docs(patches): correct manifest header to say fork tracks main, not r…
cwest Jul 2, 2026
5bbb687
πŸ› fix(kanban): active_pr respawn guard reads live PR state, not a sta…
cwest Jul 4, 2026
426a8a9
πŸ› fix(kanban): don't count a provably-done clean worker exit as a fai…
cwest Jul 4, 2026
33a3022
πŸ› fix(kanban): don't false-trip the block-loop breaker on distinct re…
cwest Jul 5, 2026
3771e4f
πŸ› fix(kanban): recover a card whose block_recurrences is already infl…
cwest Jul 5, 2026
6b294f3
πŸ› fix(kanban): route transition wakes to the origin thread, not Home …
cwest Jul 6, 2026
1b2fa69
πŸ”‡ fix(kanban): suppress human-facing wakes for write-time-sweep and n…
cwest Jul 7, 2026
45a2a2a
πŸ› fix(kanban): don't count transient-fail or reap-missed clean exits …
cwest Jul 7, 2026
f455141
πŸ› fix(kanban): make woken transition turns carry the origin session h…
cwest Jul 8, 2026
53cff68
✨ feat(kanban): inherit + reassign card origin across the spawn bound…
cwest Jul 8, 2026
e20f1ed
πŸ› fix(kanban): route an author completion to the review lane, not don…
cwest Jul 10, 2026
ad3b13d
✨ feat(kanban): team/kind-aware review-skill selection in the dispatc…
cwest Jul 10, 2026
08e4e5d
✨ feat(image_gen): nano-banana Gemini image backend (generate + edit …
cwest Jul 11, 2026
789e667
πŸ› fix(kanban): clear active_pr respawn guard on unblock from triage (…
cwest Jul 11, 2026
f03cf1c
✨ feat(image_gen): config-only resolution control for nano-banana (de…
cwest Jul 11, 2026
24a741c
πŸ› fix(image_gen): route nano-banana text-to-image through /v1/images/…
cwest Jul 12, 2026
3e2ebab
πŸ› fix(image_gen): sniff image format in save_b64_image instead of har…
cwest Jul 12, 2026
99bd7fd
✨ feat(gateway): auto-downscale oversized outbound images before nati…
cwest Jul 12, 2026
24ccb59
πŸ› fix(kanban): refuse complete_task -> done when a required PR artifa…
cwest Jul 12, 2026
a7ed14f
πŸ› fix(kanban): refuse author-lane complete on an unresolved review-el…
cwest Jul 15, 2026
659f217
πŸ› fix(kanban): skip acceptance sign-off blocks in the loop breaker (#68)
cwest Jul 19, 2026
956b04c
πŸ› fix(kanban): route a review bounce via the card's owner map, not ju…
cwest Jul 19, 2026
e0e78a0
πŸ› fix(delegate): strip kanban toolset from delegated children (#71)
cwest Jul 19, 2026
b3aa55f
πŸ› fix(kanban): make reviewer PASS->acceptance atomic via accept_task …
cwest Jul 19, 2026
eb026be
πŸ› fix(kanban): clear the active_pr respawn guard on an outer-loop fee…
cwest Jul 19, 2026
51d2750
πŸ› fix(kanban): refuse false-done for a PR-owning card in the author l…
cwest Jul 19, 2026
4a17268
πŸ› fix(kanban): recognize a no-PR edit-in-place clean exit as provably…
cwest Jul 19, 2026
bffd227
πŸ› fix(kanban): auto-advance a PR-open code card to review on clean-ex…
cwest Jul 21, 2026
48c07af
πŸ› fix(kanban): stop active_pr guard re-arming on the recovery's own c…
cwest Jul 22, 2026
b0b1468
πŸ› fix(kanban): treat a phantom/deleted PR URL as not_found so it neve…
cwest Jul 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
470 changes: 470 additions & 0 deletions .github/workflows/fork-daily-sync.yml

Large diffs are not rendered by default.

182 changes: 182 additions & 0 deletions .github/workflows/fork-secret-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
name: Fork Secret Scan

# A hard gate that keeps secrets out of this public fork. The standing rule for
# the fork is simple and absolute: no secrets, ever. Code lives here; keys live
# in .env files and Bitwarden, never in a commit.
#
# This workflow scans the patch stack β€” the commits this fork carries on top of
# its upstream release base β€” for anything secret-shaped, using gitleaks. It is
# the always-on companion to the scan baked into fork-daily-sync.yml: that one
# guards the automated daily update PR, this one guards every other path a
# commit can reach the integration branch (a hand-pushed branch, a manually
# opened pull request, a direct push).
#
# Scope: it scans only OUR commits, not all of upstream history. The fork point
# is the base tag recorded in PATCHES.md, so the scan covers exactly the changes
# we added and nothing upstream already shipped. A finding fails the job, which
# blocks the pull request β€” a person has to deal with it before the commit can
# land.
#
# Why install the gitleaks binary directly instead of using the marketplace
# action: the binary is unencumbered (the action asks for a license key on
# organization repos), and installing it ourselves lets us scan a precise commit
# range via --log-opts. The download is pinned to a release version and verified
# against a published SHA-256, the same way the ripgrep install in
# fork-daily-sync.yml is pinned.

on:
pull_request:
branches:
- cwest/integration
push:
branches:
- cwest/integration
workflow_dispatch:
inputs:
full_history:
description: 'Scan the entire git history instead of only the carried patch stack.'
type: boolean
default: false

permissions:
contents: read

# One scan per ref at a time; newer pushes supersede an in-flight scan.
concurrency:
group: fork-secret-scan-${{ github.ref }}
cancel-in-progress: true

env:
GITLEAKS_VERSION: 8.30.1
# SHA-256 of gitleaks_8.30.1_linux_x64.tar.gz, from the release checksums file.
GITLEAKS_SHA256: 551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb

jobs:
secret-scan:
name: Scan carried patches for secrets
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout (full history)
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
# Need full history so the base-tag..HEAD range resolves and gitleaks
# can walk the carried commits.
fetch-depth: 0
fetch-tags: true

- name: Install gitleaks (pinned, checksum-verified)
run: |
set -euo pipefail
tarball="gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
url="https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/${tarball}"
curl -sSfL -o "$tarball" "$url"
echo "${GITLEAKS_SHA256} ${tarball}" | sha256sum -c -
tar -xzf "$tarball" gitleaks
sudo mv gitleaks /usr/local/bin/gitleaks
rm -f "$tarball"
gitleaks version

- name: Determine the commit range to scan
id: range
run: |
set -euo pipefail
# Default: scan only the carried patch stack, base..HEAD. The base is
# the fork point recorded in PATCHES.md. Scanning from there covers
# exactly our commits and skips upstream history, which is both faster
# and avoids flagging anything that is upstream's problem, not ours.
#
# The fork tracks upstream `main` HEAD, so the base is normally a
# commit SHA (recorded as an HTML comment `<!-- Base commit: <sha> -->`
# in PATCHES.md). For backward compatibility we also accept a release
# tag (`Base tag: vX.Y.Z`). A SHA is preferred when both are present.
if [ "${{ github.event.inputs.full_history }}" = "true" ]; then
echo "mode=full" >> "$GITHUB_OUTPUT"
echo "Scanning full git history (manual override)."
exit 0
fi

# Prefer a commit SHA (main-tracking model).
base_sha="$(grep -m1 'Base commit:' PATCHES.md \
| grep -oE '[0-9a-f]{7,40}' \
| head -1 || true)"
base_ref=""
if [ -n "${base_sha}" ]; then
if git rev-parse -q --verify "${base_sha}^{commit}" >/dev/null; then
base_ref="${base_sha}"
else
echo "::error::Base commit ${base_sha} from PATCHES.md is not in the repository (fetch-depth too shallow, or the base was not pushed)."
exit 1
fi
else
# Fallback: a release tag (legacy tag-pinned model).
base_tag="$(grep -m1 'Base tag:' PATCHES.md \
| grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?' \
| head -1 || true)"
if [ -z "${base_tag}" ]; then
echo "::error::Could not read a base (Base commit / Base tag) from PATCHES.md; cannot scope the scan."
exit 1
fi
if ! git rev-parse -q --verify "refs/tags/${base_tag}" >/dev/null; then
echo "::error::Base tag ${base_tag} from PATCHES.md is not in the repository."
exit 1
fi
base_ref="refs/tags/${base_tag}"
fi

echo "mode=range" >> "$GITHUB_OUTPUT"
echo "base_ref=${base_ref}" >> "$GITHUB_OUTPUT"
echo "Scanning carried patch stack: ${base_ref}..HEAD"
git log --oneline "${base_ref}..HEAD" || true

- name: Scan for secrets
run: |
set -euo pipefail
# gitleaks exits 0 when clean, 1 when it finds a leak (the gate), and
# >1 on an internal error. A SARIF report is written for the run log.
common_args=(
--redact
--report-format sarif
--report-path gitleaks-report.sarif
--verbose
--exit-code 1
)

if [ "${{ steps.range.outputs.mode }}" = "full" ]; then
gitleaks git . "${common_args[@]}"
else
base_ref="${{ steps.range.outputs.base_ref }}"
# --log-opts is passed straight to `git log`, scoping the scan to the
# carried commits only.
gitleaks git . "${common_args[@]}" \
--log-opts="${base_ref}..HEAD"
fi
echo "No secrets found in the scanned commits."

- name: Upload scan report
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: gitleaks-report
path: gitleaks-report.sarif
if-no-files-found: ignore
retention-days: 14

- name: Result summary
if: always()
run: |
{
echo "## Fork secret scan"
echo ""
echo "- Scanner: gitleaks v${GITLEAKS_VERSION}"
echo "- Mode: \`${{ steps.range.outputs.mode }}\`"
if [ "${{ steps.range.outputs.mode }}" = "range" ]; then
echo "- Range: \`${{ steps.range.outputs.base_ref }}..HEAD\` (carried patch stack)"
fi
echo "- Outcome: \`${{ job.status }}\`"
echo ""
echo "A failure here means something secret-shaped is in a carried commit."
echo "Rotate the value, rewrite the offending commit to remove it, and"
echo "force-push the cleaned branch. Never just delete the line in a new"
echo "commit β€” the secret stays in history and must be treated as leaked."
} >> "$GITHUB_STEP_SUMMARY"
Loading
Loading