Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3983c3e
feat(helm): route sync by project board
Sep 16, 2026
e895842
fix(helm): provision a board's missing Project option instead of drop…
Sep 16, 2026
1118d1f
no-mistakes(review): Fix Helm project routing edge cases
Sep 16, 2026
0960b26
no-mistakes(review): Scope retention to remapped project and board
Sep 16, 2026
025afe3
no-mistakes(review): Persist retention and disambiguate project routing
Sep 16, 2026
defdac6
no-mistakes(review): Serialize Helm routing map updates
Sep 16, 2026
8ca94c6
no-mistakes(review): Guard pending remaps and permit empty card bodies
Sep 16, 2026
31ea244
no-mistakes(review): Discover cacheless Helm move source cards
Sep 16, 2026
8727454
no-mistakes(review): Reject duplicate cacheless move source cards
Sep 16, 2026
76643b7
no-mistakes(review): Preserve source sync and refresh move metadata
Sep 16, 2026
ee790c4
no-mistakes(review): Avoid no-op retention and clarify removed moves
Sep 16, 2026
1c98adf
no-mistakes(review): Preserve retained updates and pending moves
Sep 16, 2026
88415eb
no-mistakes(review): Fix Helm move source resolution and duplicate-ca…
Sep 16, 2026
968992a
no-mistakes(review): Add regression tests for move source resolution …
Sep 16, 2026
a0b3a86
no-mistakes(review): Exclude destination-board rows when detecting He…
Sep 16, 2026
c416c74
no-mistakes(test): Classify Helm routing documentation audiences
Sep 16, 2026
20ace54
no-mistakes(test): Fix Helm deletion board-number comparison
Sep 16, 2026
00ce4fa
no-mistakes(document): Correct Helm routing documentation
Sep 16, 2026
46f72b5
no-mistakes(lint): Fix ShellCheck warnings in Helm routing
Sep 16, 2026
31621ac
no-mistakes(review): fix: cast cached board number to string before j…
Sep 16, 2026
b231cbf
no-mistakes(review): test: add regression test for board-number type-…
Sep 16, 2026
4014377
no-mistakes(test): Skip stale post-move sync cache eviction
Sep 16, 2026
5887896
no-mistakes(lint): test: replace ambiguous && || chain with explicit …
Sep 16, 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
8 changes: 8 additions & 0 deletions .agents/skills/project-management/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ Clone into `projects/<name>` and add the registry entry only after the destinati
A `no-mistakes` or `no-mistakes-prod-only` project must have an `origin` remote and must complete the initialization procedure below, because a conditional policy's product-facing work runs the pipeline while its internal-only work still takes the direct PR.
A `direct-PR` project needs an `origin` remote but skips no-mistakes initialization.
A `local-only` project may have no remote and skips no-mistakes initialization.
When Helm is enabled (`config/helm.json` exists), also offer the new project a
dedicated GitHub Project board or the shared Helm default; skipping that choice
is fine and keeps future cards on the default. If the captain chooses a
dedicated board, run `bin/fm-helm-project-map.sh link <name>` after the project
is registered.

## Create a project

Expand All @@ -69,6 +74,9 @@ After remote creation succeeds, clone it locally, add the registry entry, and in

For a purely `local-only` project, create a local Git repository under its unused `projects/<name>` path, add the registry entry, and make no GitHub call.
The captain's request to create that local project authorizes this local initialization, but it does not authorize an unmentioned remote repository.
When Helm is enabled (`config/helm.json` exists), offer the same dedicated-board
or shared-default choice for the new project. If a dedicated board is accepted,
run `bin/fm-helm-project-map.sh link <name>` after registration.

## Initialize

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Launching a supported harness inside it instantiates your first mate - and makes
- **Optional secondmates** - opt in to persistent second mates that run from isolated firstmate homes with their own `FM_HOME`, state, projects, and session lock, either locally or as a whole home on an SSH-reachable host, with guarded updates and recovery that never turns an unavailable remote route into a local replacement.
- **Event-driven, zero-token supervision** - a bash watcher sleeps on the fleet and wakes the first mate only when something needs you; verified primary harnesses also get a turn-end backstop that blocks or follows up on a blind stop when work is under way and supervision is not live.
- **Optional Relay** - opt in with one local `.env` pairing token so firstmate can answer your public mentions on X and Discord alike, act on normal reversible mention requests through the same lifecycle as chat requests, acknowledge spawned work, and post up to three public-safe completion follow-ups within seven days for genuine milestones and the final outcome without changing non-Relay behavior; a final reply promised in a thread becomes durable state that is reconciled from disk, so a restart or a compacted conversation cannot lose it; dry-run preview records would-be replies and dismissals locally before go-live.
- **Optional Helm board** - opt in with a home-local `config/helm.json` so a GitHub Project v2 board follows the backlog and can submit durable dispatch requests back to firstmate.
- **Optional Helm boards** - opt in with a home-local `config/helm.json` so a default GitHub Project v2 board follows the backlog; `bin/fm-helm-project-map.sh` can route registered projects to dedicated or intentionally shared boards and submit durable dispatch requests back to firstmate.
- **Strict project boundary** - the first mate is read-only over your projects except for the narrow guarded and captain-approved operations authorized by [hard rule 1](AGENTS.md#1-identity-and-prime-directives), including fleet sync's guarded safe branch pruning; crewmates make every other project change behind the configured merge authority.
- **Restart-proof** - all state lives on disk and in the active session backend (tmux by hard default, herdr or cmux when selected or auto-detected, zellij/orca when explicitly selected); kill the session anytime and the next one reconciles, including confirmed-dead secondmate agents, and carries on.

Expand Down
18 changes: 17 additions & 1 deletion bin/fm-bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1124,9 +1124,10 @@ EOF
# surface as durable check wakes. The sync itself aggregates local secondmate
# backlogs, so a secondmate needs no competing board writer or copied config.
helm_watch_setup() {
local sync_shim board_shim sync_body board_body
local sync_shim board_shim reconcile_shim sync_body board_body reconcile_body
sync_shim="$STATE/helm-sync.check.sh"
board_shim="$STATE/helm-board.check.sh"
reconcile_shim="$STATE/helm-reconcile.check.sh"

if [ ! -f "$CONFIG/helm.json" ]; then
if [ -e "$sync_shim" ] || [ -L "$sync_shim" ] || [ -e "$STATE/helm-sync.check-trust" ] || [ -L "$STATE/helm-sync.check-trust" ]; then
Expand All @@ -1139,6 +1140,11 @@ helm_watch_setup() {
"$SCRIPT_DIR/fm-check-unregister.sh" helm-board >/dev/null 2>&1 \
|| echo "HELM: could not retire Helm watcher board poll"
fi
if [ -e "$reconcile_shim" ] || [ -L "$reconcile_shim" ] || [ -e "$STATE/helm-reconcile.check-trust" ] || [ -L "$STATE/helm-reconcile.check-trust" ]; then
FM_HOME="$FM_HOME" FM_ROOT_OVERRIDE="$FM_ROOT" FM_STATE_OVERRIDE="$STATE" \
"$SCRIPT_DIR/fm-check-unregister.sh" helm-reconcile >/dev/null 2>&1 \
|| echo "HELM: could not retire Helm watcher reconciliation"
fi
return 0
fi

Expand All @@ -1152,17 +1158,27 @@ EOF
#!/usr/bin/env bash
exec "$FM_ROOT/bin/fm-helm-poll.sh"
EOF
)
reconcile_body=$(cat <<EOF
#!/usr/bin/env bash
exec "$FM_ROOT/bin/fm-helm-reconcile.sh"
EOF
)
x_mode_write_if_changed "$sync_shim" "$sync_body" 700 \
|| { echo "HELM: could not arm Helm watcher sync"; return 0; }
x_mode_write_if_changed "$board_shim" "$board_body" 700 \
|| { echo "HELM: could not arm Helm watcher board poll"; return 0; }
x_mode_write_if_changed "$reconcile_shim" "$reconcile_body" 700 \
|| { echo "HELM: could not arm Helm watcher reconciliation"; return 0; }
FM_HOME="$FM_HOME" FM_ROOT_OVERRIDE="$FM_ROOT" FM_STATE_OVERRIDE="$STATE" \
"$SCRIPT_DIR/fm-check-register.sh" helm-sync >/dev/null 2>&1 \
|| echo "HELM: could not arm Helm watcher sync"
FM_HOME="$FM_HOME" FM_ROOT_OVERRIDE="$FM_ROOT" FM_STATE_OVERRIDE="$STATE" \
"$SCRIPT_DIR/fm-check-register.sh" helm-board >/dev/null 2>&1 \
|| echo "HELM: could not arm Helm watcher board poll"
FM_HOME="$FM_HOME" FM_ROOT_OVERRIDE="$FM_ROOT" FM_STATE_OVERRIDE="$STATE" \
"$SCRIPT_DIR/fm-check-register.sh" helm-reconcile >/dev/null 2>&1 \
|| echo "HELM: could not arm Helm watcher reconciliation"
}

crew_dispatch_validate() {
Expand Down
Loading
Loading