picatz / picatz/flowstate

.claude/hooks: a removed guard package denies every guarded tool, and three smaller gaps in the identity

Open
#1,964 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
9
Forks
0
Avg merge
3h 3m
Merged PRs (30d)
509

Description

Findings from the exact-head review of #1942, deferred here rather than taken as a fifth head. Recorded against 38d29644ee81b04586eacc5eb11ebc4d539ebc6e.

1. A removed guard package denies every guarded tool, not only its own

build-hooks.sh denies when any configured hook's package directory is absent, and source-id.sh fails on the same missing directory, so no guard can establish currency. Removing one package therefore denies Edit, MultiEdit, Write and Bash together. A pre-tool denial is not approvable, so only Read, Grep and Glob remain, and a restart repeats the same short-circuit: the directory has to be restored from outside the session.

Verified by removing only the merge guard's package from a healthy fixture, after which all four guards exited 2.

This is not a regression. On main a deleted package made the hook's go run exit 1, which is non-blocking, so the new behavior is strictly more fail-closed and matches the fail-closed invariant. Every denial also names the package to restore. What is wrong is the scope claim: docs/agents/README.md says "a guard whose package is gone denies", in the singular, and the test asserts only that the removed guard's own launcher denies. The message the other three print, that they are out of date and could not be rebuilt, is not a true statement about them.

Options, smallest first: correct the documentation and the message to say that a missing package denies every guard, or record a missing package the way a package that failed to compile is already recorded, drop it from the manifest so the identity still resolves, publish the rest, and deny only for that name. The second always leaves a repair path, since removing the merge guard leaves editing available and removing the edit guard leaves the shell.

2. A guard recorded as unbuilt is never retried within a generation

A hook named in the unbuilt list satisfies the completeness check, so the launcher keeps warning and letting calls through without retrying the build. That is the intended trade against an endless rebuild, and it is loud rather than silent, but a failure from a non-source cause such as a killed compile or a full disk sticks for the rest of the generation, and the warning then says the sources do not compile, which is not what happened. Repair exists in session, so this is not a lockout. Either retry once per generation, or word the warning as "could not be built".

3. A directory or glob embed escapes the identity after the first build

The extra-input manifest records the embedded files the compiler names at build time, so adding a new file to an already-embedded directory changes what the build produces while changing neither the sources nor the recorded list. Verified: editing an embedded file changed the identity, adding a sibling did not, and the stale binary was judged current.

Not reachable today, since no package in the guards' closure embeds anything. It becomes reachable the first time one does. Store the embed patterns as well and re-expand them when computing the identity.

4. The identity script contradicts the build script

source-id.sh still justifies its extension list by saying the build refuses to publish when the compiler reports an input outside it. The build no longer refuses; it records those inputs instead, and says so in its own comment. The same file states the real behavior correctly a few lines later. Delete the stale clause.

Acceptance

The documentation and the denial message agree with what a missing package actually does, an unbuilt guard is retried or described accurately, the identity covers a directory embed, and no comment describes a refusal the code does not perform.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with build-hooks.sh and source-id.sh at commit 38d29644ee81b04586eacc5eb11ebc4d539ebc6e, then read docs/agents/README.md and the existing guard package and identity behavior. Reproduce the missing-package and unbuilt cases described in the issue, and inspect how extra-input manifests handle directory or glob embeds. Done means the documentation and denial message match behavior, unbuilt guards are retried or described accurately, embed identities stay current, and stale comments are removed.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
build-system, security, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.