chore: sync local alignment guidance and managed hooks #10

Merged
jercik merged 1 commit from chore/align-local-forge into main 2026-10-24 06:36:32 +00:00
Owner

Updates declaration-check guidance for Align's local command and regenerates managed hooks and review configuration from Align #809. Interrupted hooks clean up their snapshots, and the updated review wrapper retains the zero-failed-unit gate.

Merge after Align 13 is published and verified.

Updates declaration-check guidance for Align's local command and regenerates managed hooks and review configuration from [Align #809](https://code.j4k.dev/j4k/align/pulls/809). Interrupted hooks clean up their snapshots, and the updated review wrapper retains the zero-failed-unit gate. Merge after Align 13 is published and verified.
chore: sync local alignment guidance and managed hooks
All checks were successful
Checks / pr-flow-canary (pull_request) Has been skipped
Checks / reuse (pull_request) Successful in 5s
commit-msg / commitlint (pull_request) Successful in 12s
Checks / quality-checks (26.5.0) (pull_request) Successful in 27s
Checks / quality-checks (24.15.0) (pull_request) Successful in 27s
Review / Review (pull_request_target) Successful in 4m32s
b0d9dd7cf9

Review 01M5N1NC2FHD59FKG0EC27AZW3 — head b0d9dd7cf9bc19ee852218522ceab3ecd12df5c6

Review — j4k-oss/fta-check @ 4900e92f07

Scope: diff against base tree 3feb72321423
Review finished: 10 succeeded, 0 failed
Triage: settled
Facts: current review-wide projection

Computed under:

{
  "abandonment": "abandonment-v1",
  "anchor_recipe": 1,
  "batch_policy": "batch-v1",
  "coverage": "coverage-v3",
  "dispatch_policy": "dispatch-v2",
  "grounder_version": 1,
  "grounding_read_rule": "grounding-read-v1",
  "promotion_policy": "promotion-v1",
  "report": "report-v5",
  "tally": "tally-v1",
  "triage_settle": "triage-settle-v2"
}

Findings (1)

medium — The cleanup watcher can finish before the untracked checkout recreates the snapshot

  • claim: 01M5N1SP26Y90W9Y1XF4VY2HJS
  • anchor: .githooks/commit-msg (snippet)
git --git-dir="$git_common_dir" -c worktree.useRelativePaths=false -c core.hooksPath=/dev/null worktree add --quiet --detach "$snapshot_dir" "$snapshot_commit" 6>&-
  • lens: aposd-plain · arm: default
  • verdicts: 1 valid / 0 invalid / 0 uncertain
    • pass 01M5N1VA2QPMG0QD6JYKGV2WGZ · valid: The exact-grounded anchor shows worktree creation directly invokes Git and closes fd 6. The reviewer supplies a specific trace: only run_step publishes a process group, so EOF during this checkout makes watch_snapshot remove resources without stopping their creator. The reported gated-Git experiment places cleanup before real checkout and observes the directory and registration returning afterward; this is a coherent scheduling interleaving, not an assertion that every checkout timing recreates them. Descriptor closure is not process ownership, and successful cleanup of run_step checks does not cover this call site. This supports the APoSD concern that the cleanup abstraction leaves callers responsible for coordinating process registration and resource lifetime; pulling that coordination into the execution owner addresses the demonstrated defect. Medium is appropriate. The trace and experiment are reviewer-reported evidence, not independently reproduced.
  • duplicates: 01M5N1TW78N7VMTYCRNGGTBGRP (general-bug)
  • disposition: none

Killing the hook during worktree creation can leave a detached snapshot and its Git registration behind after the cleanup watcher has exited. The new cleanup abstraction does not own every process that can create the resources it removes, so its SIGKILL recovery depends on which operation is running.

The worktree-add command closes descriptor 6 but runs outside run_step. Only run_step sends a process-group ID to watch_snapshot. If the hook is killed during this foreground checkout, the watcher receives EOF with an empty process_group, removes the snapshot, and exits without stopping or waiting for checkout. The surviving checkout can then recreate the directory and registration. Closing the descriptor prevents delayed EOF but does not coordinate the child with cleanup.

Put worktree creation under the same process-lifetime owner as the checks: the supervisor must know the checkout's process group and stop it before removing its resources. Hide descriptor handling and process registration behind that execution interface so callers cannot independently satisfy one half of the cleanup contract.

I traced run_step, watch_snapshot, stop_checks, and remove_snapshot_files in .githooks/commit-msg. Running node /app/probe-hook-cleanup.mjs exercised the unchanged hook in an isolated Git repository, with pnpm stubbed and a Git wrapper gating worktree add immediately before invoking real Git. After SIGKILL of the hook, the watcher removed the snapshot; releasing checkout then returned status 0 and left both the recreated snapshot and its worktree registration. This tests a controlled scheduling interleaving, not a full dependency installation or a naturally timed slow checkout.

A regression test that kills the hook while checkout remains active and verifies that the checkout terminates before cleanup, with neither directory nor registration returning afterward, would establish the required ownership guarantee.

Other claims

  • grounding-pending (0)
  • ungrounded (0)
  • rejected (0)
  • duplicate-of (1)
    • 01M5N1TW78N7VMTYCRNGGTBGRP medium — The watcher removes the snapshot while its checkout is still running → 01M5N1SP26Y90W9Y1XF4VY2HJS
  • unadjudicated (0)

Coverage

Coverage pass: 01M5N1NPZCKR0Y3S2PZMVCR8Q4
Accounting: complete (all slots terminal; see slot results for failures)
Slot health: healthy

lens part arm unit status runs loss
general-bug whole default claims-emitted 1 no
writing-quality whole default no-claims 1 no
test-trimming whole default no-claims 1 no
restated-sets whole default no-claims 1 no
project-docs whole default no-claims 1 no
unix-cli whole default no-claims 1 no
use-effect whole default no-claims 1 no
module-design whole default no-claims 1 no
aposd-plain whole default claims-emitted 1 no
react whole default no-claims 1 no
<!-- review:summary --> **Review** `01M5N1NC2FHD59FKG0EC27AZW3` — head `b0d9dd7cf9bc19ee852218522ceab3ecd12df5c6` # Review — j4k-oss/fta-check @ 4900e92f0782 Scope: diff against base tree `3feb72321423` Review finished: 10 succeeded, 0 failed Triage: settled Facts: current review-wide projection Computed under: ```json { "abandonment": "abandonment-v1", "anchor_recipe": 1, "batch_policy": "batch-v1", "coverage": "coverage-v3", "dispatch_policy": "dispatch-v2", "grounder_version": 1, "grounding_read_rule": "grounding-read-v1", "promotion_policy": "promotion-v1", "report": "report-v5", "tally": "tally-v1", "triage_settle": "triage-settle-v2" } ``` ## Findings (1) ### medium — The cleanup watcher can finish before the untracked checkout recreates the snapshot - claim: `01M5N1SP26Y90W9Y1XF4VY2HJS` - anchor: `.githooks/commit-msg` (snippet) ``` git --git-dir="$git_common_dir" -c worktree.useRelativePaths=false -c core.hooksPath=/dev/null worktree add --quiet --detach "$snapshot_dir" "$snapshot_commit" 6>&- ``` - lens: aposd-plain · arm: default - verdicts: 1 valid / 0 invalid / 0 uncertain - pass `01M5N1VA2QPMG0QD6JYKGV2WGZ` · valid: The exact-grounded anchor shows worktree creation directly invokes Git and closes fd 6. The reviewer supplies a specific trace: only run_step publishes a process group, so EOF during this checkout makes watch_snapshot remove resources without stopping their creator. The reported gated-Git experiment places cleanup before real checkout and observes the directory and registration returning afterward; this is a coherent scheduling interleaving, not an assertion that every checkout timing recreates them. Descriptor closure is not process ownership, and successful cleanup of run_step checks does not cover this call site. This supports the APoSD concern that the cleanup abstraction leaves callers responsible for coordinating process registration and resource lifetime; pulling that coordination into the execution owner addresses the demonstrated defect. Medium is appropriate. The trace and experiment are reviewer-reported evidence, not independently reproduced. - duplicates: `01M5N1TW78N7VMTYCRNGGTBGRP` (general-bug) - disposition: none > Killing the hook during worktree creation can leave a detached snapshot and its Git registration behind after the cleanup watcher has exited. The new cleanup abstraction does not own every process that can create the resources it removes, so its SIGKILL recovery depends on which operation is running. > > The worktree-add command closes descriptor 6 but runs outside run_step. Only run_step sends a process-group ID to watch_snapshot. If the hook is killed during this foreground checkout, the watcher receives EOF with an empty process_group, removes the snapshot, and exits without stopping or waiting for checkout. The surviving checkout can then recreate the directory and registration. Closing the descriptor prevents delayed EOF but does not coordinate the child with cleanup. > > Put worktree creation under the same process-lifetime owner as the checks: the supervisor must know the checkout's process group and stop it before removing its resources. Hide descriptor handling and process registration behind that execution interface so callers cannot independently satisfy one half of the cleanup contract. > > I traced run_step, watch_snapshot, stop_checks, and remove_snapshot_files in .githooks/commit-msg. Running node /app/probe-hook-cleanup.mjs exercised the unchanged hook in an isolated Git repository, with pnpm stubbed and a Git wrapper gating worktree add immediately before invoking real Git. After SIGKILL of the hook, the watcher removed the snapshot; releasing checkout then returned status 0 and left both the recreated snapshot and its worktree registration. This tests a controlled scheduling interleaving, not a full dependency installation or a naturally timed slow checkout. > > A regression test that kills the hook while checkout remains active and verifies that the checkout terminates before cleanup, with neither directory nor registration returning afterward, would establish the required ownership guarantee. ## Other claims - grounding-pending (0) - ungrounded (0) - rejected (0) - duplicate-of (1) - `01M5N1TW78N7VMTYCRNGGTBGRP` medium — The watcher removes the snapshot while its checkout is still running → `01M5N1SP26Y90W9Y1XF4VY2HJS` - unadjudicated (0) ## Coverage Coverage pass: 01M5N1NPZCKR0Y3S2PZMVCR8Q4 Accounting: complete (all slots terminal; see slot results for failures) Slot health: healthy | lens | part | arm | unit status | runs | loss | | --- | --- | --- | --- | --- | --- | | general-bug | whole | default | claims-emitted | 1 | no | | writing-quality | whole | default | no-claims | 1 | no | | test-trimming | whole | default | no-claims | 1 | no | | restated-sets | whole | default | no-claims | 1 | no | | project-docs | whole | default | no-claims | 1 | no | | unix-cli | whole | default | no-claims | 1 | no | | use-effect | whole | default | no-claims | 1 | no | | module-design | whole | default | no-claims | 1 | no | | aposd-plain | whole | default | claims-emitted | 1 | no | | react | whole | default | no-claims | 1 | no |
@ -146,2 +205,3 @@
exec 6> >(set -m; watch_snapshot <&0 > /dev/null &)
# Relative worktree paths would upgrade the repository format; post-checkout hooks must not run here.
git --git-dir="$git_common_dir" -c worktree.useRelativePaths=false -c core.hooksPath=/dev/null worktree add --quiet --detach "$snapshot_dir" "$snapshot_commit"
git --git-dir="$git_common_dir" -c worktree.useRelativePaths=false -c core.hooksPath=/dev/null worktree add --quiet --detach "$snapshot_dir" "$snapshot_commit" 6>&-

medium — The cleanup watcher can finish before the untracked checkout recreates the snapshot

Killing the hook during worktree creation can leave a detached snapshot and its Git registration behind after the cleanup watcher has exited. The new cleanup abstraction does not own every process that can create the resources it removes, so its SIGKILL recovery depends on which operation is running.

The worktree-add command closes descriptor 6 but runs outside run_step. Only run_step sends a process-group ID to watch_snapshot. If the hook is killed during this foreground checkout, the watcher receives EOF with an empty process_group, removes the snapshot, and exits without stopping or waiting for checkout. The surviving checkout can then recreate the directory and registration. Closing the descriptor prevents delayed EOF but does not coordinate the child with cleanup.

Put worktree creation under the same process-lifetime owner as the checks: the supervisor must know the checkout's process group and stop it before removing its resources. Hide descriptor handling and process registration behind that execution interface so callers cannot independently satisfy one half of the cleanup contract.

I traced run_step, watch_snapshot, stop_checks, and remove_snapshot_files in .githooks/commit-msg. Running node /app/probe-hook-cleanup.mjs exercised the unchanged hook in an isolated Git repository, with pnpm stubbed and a Git wrapper gating worktree add immediately before invoking real Git. After SIGKILL of the hook, the watcher removed the snapshot; releasing checkout then returned status 0 and left both the recreated snapshot and its worktree registration. This tests a controlled scheduling interleaving, not a full dependency installation or a naturally timed slow checkout.

A regression test that kills the hook while checkout remains active and verifies that the checkout terminates before cleanup, with neither directory nor registration returning afterward, would establish the required ownership guarantee.

lens aposd-plain · arm default · tally 1 valid / 0 invalid / 0 uncertain
claim 01M5N1SP26Y90W9Y1XF4VY2HJS of review 01M5N1NC2FHD59FKG0EC27AZW3

<!-- review:claim:01M5N1SP26Y90W9Y1XF4VY2HJS --> **medium** — The cleanup watcher can finish before the untracked checkout recreates the snapshot > Killing the hook during worktree creation can leave a detached snapshot and its Git registration behind after the cleanup watcher has exited. The new cleanup abstraction does not own every process that can create the resources it removes, so its SIGKILL recovery depends on which operation is running. > > The worktree-add command closes descriptor 6 but runs outside run_step. Only run_step sends a process-group ID to watch_snapshot. If the hook is killed during this foreground checkout, the watcher receives EOF with an empty process_group, removes the snapshot, and exits without stopping or waiting for checkout. The surviving checkout can then recreate the directory and registration. Closing the descriptor prevents delayed EOF but does not coordinate the child with cleanup. > > Put worktree creation under the same process-lifetime owner as the checks: the supervisor must know the checkout's process group and stop it before removing its resources. Hide descriptor handling and process registration behind that execution interface so callers cannot independently satisfy one half of the cleanup contract. > > I traced run_step, watch_snapshot, stop_checks, and remove_snapshot_files in .githooks/commit-msg. Running node /app/probe-hook-cleanup.mjs exercised the unchanged hook in an isolated Git repository, with pnpm stubbed and a Git wrapper gating worktree add immediately before invoking real Git. After SIGKILL of the hook, the watcher removed the snapshot; releasing checkout then returned status 0 and left both the recreated snapshot and its worktree registration. This tests a controlled scheduling interleaving, not a full dependency installation or a naturally timed slow checkout. > > A regression test that kills the hook while checkout remains active and verifies that the checkout terminates before cleanup, with neither directory nor registration returning afterward, would establish the required ownership guarantee. lens `aposd-plain` · arm `default` · tally 1 valid / 0 invalid / 0 uncertain claim `01M5N1SP26Y90W9Y1XF4VY2HJS` of review `01M5N1NC2FHD59FKG0EC27AZW3`
Author
Owner

Declining this hardening change for the owned-repository migration at b0d9dd7cf9. I traced the direct worktree-add call and the watcher: checkout does not register a process group, so the reported hook-only SIGKILL ordering is a plausible cleanup gap. I am not claiming it is fixed or disproved. The reported experiment gates Git before the real checkout starts. This checkout uses /opt/homebrew/bin/git without that gate. Git attribute inspection found no assigned filter on any of this repository’s 51 tracked paths. The user explicitly limited this migration to our actual repositories and asked us to avoid expanding tooling for unusual edge cases. We retain that scope and accept this limitation; no follow-up PR or broader cleanup guarantee is claimed.

<!-- gh-feedback:reply-to:182205 --> Declining this hardening change for the owned-repository migration at b0d9dd7cf9bc19ee852218522ceab3ecd12df5c6. I traced the direct worktree-add call and the watcher: checkout does not register a process group, so the reported hook-only SIGKILL ordering is a plausible cleanup gap. I am not claiming it is fixed or disproved. The reported experiment gates Git before the real checkout starts. This checkout uses /opt/homebrew/bin/git without that gate. Git attribute inspection found no assigned filter on any of this repository’s 51 tracked paths. The user explicitly limited this migration to our actual repositories and asked us to avoid expanding tooling for unusual edge cases. We retain that scope and accept this limitation; no follow-up PR or broader cleanup guarantee is claimed.
jercik marked this conversation as resolved
jercik merged commit 75e1fb4b5e into main 2026-10-24 06:36:32 +00:00
jercik deleted branch chore/align-local-forge 2026-10-24 06:36:33 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
j4k-oss/fta-check!10
No description provided.