Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 7 additions & 3 deletions bin/fm-fleet-snapshot.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@
# normalized current_role, requires_child_metadata, blocked_by_ids,
# unresolved_blocker_ids, captain_actionable, hold_set, hold_age_days,
# and hold_bucket fields.
# Repeated blocker tokens remain ordered; a blocker resolves only when its
# structured record is Done, and missing ids stay open.
# Repeated blocker tokens remain ordered; a blocker resolves when its
# structured record is Done, or when no record for that id exists at all
# in this snapshot (already torn down or aged out of retention) - it
# stays open only when a record for it exists and is not Done, matching
# tasks-axi's own dependency resolution so the two readers of one backlog
# cannot disagree on whether a since-archived blocker still blocks.
# There is no separate decision type: any captain-held task is the same
# primitive, whatever kind its row carries.
# hold_bucket is the single classification for every captain hold, decided
Expand Down Expand Up @@ -528,7 +532,7 @@ backlog_json() { # [<backlog-path>] - defaults to this home's $BACKLOG
. as $record
| .unresolved_blocker_ids = [
$record.blocked_by_ids[] as $blocker
| select($resolved_ids[$blocker] != true)
| select(($resolved_ids | has($blocker)) and ($resolved_ids[$blocker] != true))
| $blocker
]
| .current_role =
Expand Down
15 changes: 12 additions & 3 deletions tests/fm-bearings-snapshot.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ write_domain_alpha_fixture() { # <parent-home> <secondmate-home>

## Queued
- [ ] legal-release - Release approval blocked-by: external-legal - external legal dependency (repo: sample) (kind: ship)
- [ ] external-legal - External legal review (repo: sample) (kind: ship) (since 2026-07-13)

## Done
EOF
Expand Down Expand Up @@ -803,6 +804,7 @@ test_parent_evidence_reconciles_by_verb_and_key() {

## Queued
- [ ] legal-release - Legal release blocked-by: external-legal - legal review (repo: sample) (kind: ship)
- [ ] external-legal - External legal review (repo: sample) (kind: ship) (since 2026-07-11)

## Done
EOF
Expand All @@ -811,6 +813,7 @@ EOF

## Queued
- [ ] vendor-release - Vendor release blocked-by: external-vendor - vendor review (repo: sample) (kind: ship)
- [ ] external-vendor - External vendor review (repo: sample) (kind: ship) (since 2026-07-11)

## Done
EOF
Expand Down Expand Up @@ -1228,6 +1231,7 @@ test_undated_hold_phrasing_and_aging_projection() {
NOT REQUIRED - the remote decision is moot.
- [ ] mate-aged - Remote aged call (repo: firstmate) (kind: captain) (since 2026-06-01) (hold: choose a remote route) (hold-kind: captain)
Captain hold set: 2026-06-01T00:00:00Z
- [ ] missing-remote-blocker - Real still-open remote blocker (repo: firstmate) (kind: ship)

## Done
EOF
Expand All @@ -1237,6 +1241,7 @@ EOF
## Queued
- [ ] parked-hold - Parked style call (repo: firstmate) (kind: ship) (since 2026-07-10) (hold: not urgent) (hold-kind: captain)
- [ ] blocked-parked - Blocked parked call blocked-by: missing-blocker (repo: firstmate) (kind: captain) (hold: parked) (hold-kind: captain)
- [ ] missing-blocker - Real still-open blocker (repo: firstmate) (kind: ship)
- [ ] future-parked - Parked style call for later (repo: firstmate) (kind: captain) (hold: parked) (hold-kind: captain) (hold-until: 2026-08-01)
- [ ] due-parked - Parked style call now due (repo: firstmate) (kind: captain) (hold: parked) (hold-kind: captain) (hold-until: 2026-07-11)
- [ ] due-superseded - Superseded call now due (repo: firstmate) (kind: captain) (hold: SUPERSEDED) (hold-kind: captain) (hold-until: 2026-07-11)
Expand Down Expand Up @@ -1358,6 +1363,7 @@ test_blocked_deferred_hold_has_concrete_disclosure() {

## Queued
- [ ] only-blocked-parked - Blocked parked call blocked-by: missing-blocker (repo: firstmate) (kind: captain) (hold: parked) (hold-kind: captain) (hold-until: 2026-07-11)
- [ ] missing-blocker - Real still-open blocker (repo: firstmate) (kind: ship)

## Done
EOF
Expand Down Expand Up @@ -1388,6 +1394,7 @@ test_revealed_deferred_holds_show_their_deferral_reason() {
- [ ] reveal-aged - Aged undated call (repo: firstmate) (kind: captain) (since 2026-06-01) (hold: choose a route) (hold-kind: captain)
Captain hold set: 2026-06-01T00:00:00Z
- [ ] reveal-live - 123456789012345678901234567890123456789012345678901234567890 (repo: firstmate) (kind: captain) (hold: choose A) (hold-kind: captain)
- [ ] missing-blocker-1234567890123456789012345678901234567890 - Real still-open blocker (repo: firstmate) (kind: ship)

## Done
EOF
Expand Down Expand Up @@ -2317,6 +2324,8 @@ test_working_captain_holds_keep_their_bucket_surfaces() {
Captain hold set: 2026-06-01T00:00:00Z

## Queued
- [ ] blocker-alpha-123456789012345678901234567890 - Real still-open blocker alpha (repo: sample) (kind: ship)
- [ ] blocker-beta-123456789012345678901234567890 - Real still-open blocker beta (repo: sample) (kind: ship)

## Done
EOF
Expand Down Expand Up @@ -2830,9 +2839,9 @@ EOF
mv "$ha/data/backlog.next" "$ha/data/backlog.md"
json=$(run "$home" "$fakebin" --json)
printf '%s' "$json" | jq -e '
(.decisions_open | any(.id == "home-assistant/captain-run") | not)
and (.gates | any(.id == "captain-run" and .owner == "home-assistant" and .blocked_by == "missing"))
' >/dev/null || fail "a missing Home Assistant blocker was treated as Done: $json"
([.decisions_open[] | select(.id == "home-assistant/captain-run")] | length) == 1
and (.gates | any(.id == "captain-run" and .owner == "home-assistant") | not)
' >/dev/null || fail "a blocker id with no backlog row (already torn down) was not treated as resolved: $json"

sed 's/(kind: program)/(kind: mystery)/' "$hibit/data/backlog.md" > "$hibit/data/backlog.next"
mv "$hibit/data/backlog.next" "$hibit/data/backlog.md"
Expand Down
6 changes: 3 additions & 3 deletions tests/fm-fleet-snapshot-view.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -406,9 +406,9 @@ EOF
printf '%s' "$out" | jq -e '
.backlog.records[] | select(.id == "captain-run")
| .blocked_by_ids == ["worker", "missing"]
and .unresolved_blocker_ids == ["missing"]
and .captain_actionable == false
' >/dev/null || fail "a missing blocker was incorrectly treated as resolved: $out"
and .unresolved_blocker_ids == []
and .captain_actionable == true
' >/dev/null || fail "a blocker id with no backlog row (already torn down) was not treated as resolved: $out"
pass "backlog normalization preserves strict roles and resolves every blocker compatibly"
}

Expand Down
Loading