docs: record that the session-start hook stores an absolute path (task 0042) #51
Reference in New Issue
Block a user
Delete Branch "task-0042-verify-hook-path-resolution"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Tasks:
0042-verify-hook-path-resolution.md(implemented) ·0043·0044·0045(planned)Summary
Resolves the
nix-flake-packagingspec's one open verification item — whether the session-start hook records the entrypoint's absolute path or the bare binary name — by observation against the installed SDK, then breaks the follow-on work into tasks.The answer is the unfavourable one.
resolvePortableHookCommandreturns the bare name only when aPATHentry realpath-matches the entrypoint. npm symlinks itsbinentry straight atdist/main.js, so that match succeeds; Nix installs a generated wrapper script invokingnode <path>, whose realpath is the wrapper, so the match cannot succeed and the absolute store path is recorded.Verified twice: by probing the SDK with both install shapes, and by building the flake and driving the installed binary against a temporary
HOME, which wrote a/nix/store/...path into~/.claude/settings.json.Changes in this PR:
src/commands/setup.ts— the help text says to re-runsetup hooksafter an upgrade..claude/spec/nix-flake-packaging.md— the open verification item becomes a resolved finding, with the mechanism recorded.CLAUDE.md— a Gotchas entry, since the belief thatbinaryNamesmakes the hook portable was wrong.package.nix— comment only; its forward reference to this task is corrected..claude/tasks/0043–0045— the follow-on breakdown described below..claude/CONTEXT.md— four new terms, and amendments tosetupandSessionStart hook.No behaviour changes. Typecheck and the fast tier (410 tests) pass.
The mitigation's framing turned out to be too narrow
Grilling the result found a larger defect underneath the one this task was written for.
The maintainer's agent configuration is generated declaratively, so
~/.claude/settings.jsonand the installed Agent Skill are both read-only symlinks into the Nix store.setup hookscannot write at all;setupcrashes on an unhandled filesystem error. The Skill has been hand-copied into the operator's own configuration and has already drifted — 48 lines there against the package's 39.So the recorded path's shape is one defect, and the deeper one is that
setupis write-only against a target some operators cannot let it write. Prior art draws the line in the same place: zoxide and atuin record a bare name into user-owned config, while home-manager persists absolute store paths precisely because it regenerates the file. gitea-axi writes user-owned state and should follow the first convention — and should also offer the second path for operators who generate theirs.Three tasks follow:
PATH, so the hook survives an upgrade on any wrapper-based install. Fixes theisManagedHookmarker-substring coupling with it, and dropspackage.nix'spostUnpackrename.The module follows the conventions measured across all 445 home-manager
programs/*modules:mkEnableOptiongate so import is inert (91%), overridablepackageoption (87%), module installs the package by default (79%),nullable = trueas the documented opt-out (51%).Deviations
package.nix'spostUnpackrename was kept, not deleted. Task 0042's evidence section says to delete it "as part of this task", which conflicts with its own acceptance criterion 4. The conflict resolves on that section's wording: the deletion is conditioned on "once the hook no longer depends on the entrypoint path", which criterion 4 puts out of scope. Deleting it now would leave the build tree at a path with nogitea-axisegment — whichisManagedHookstill requires — andtest/setup.test.tswould fail insidecheckPhase. Its comment was rewritten instead. Task 0043 removes it.The re-run-after-upgrade help text stays, knowing 0043 removes it. It is accurate until then, and 0043 carries its removal as an acceptance criterion. Reverting it pre-emptively would leave the branch documenting a silent failure it does nothing about.
One sentence beyond the strict ask. The help text asserted "Both are idempotent" unqualified, which the finding recorded in this same commit makes false for the duplicate-append case. It is now caveated rather than left contradicting the spec.
The spec is left contradicting itself, deliberately.
nix-flake-packaging.mdstill lists a home-manager module under Out of Scope. Revising that is task 0045's job — it is a design decision reversal that belongs with an ADR and the work, not a task-writing side effect.Review
Risk
Overall: LOW
Unaddressed findings
Standards — possible Duplicated Code / Shotgun Surgery (judgement call). The wrapper-vs-symlink realpath mechanism is stated in the spec, in
CLAUDE.md, and inpackage.nix's comment, so a future correction touches several files. Not addressed: the three are deliberately different audiences (design record, agent gotcha, inline rationale), and collapsing them into cross-references would make each less useful at its own site.