docs: record that the session-start hook stores an absolute path (task 0042) #51
@@ -156,16 +156,37 @@ _Avoid_: mock mode, stub mode
|
|||||||
|
|
||||||
### Distribution
|
### Distribution
|
||||||
|
|
||||||
**Agent Skill**: The markdown file bundled inside the npm package and installed to `~/.claude/skills/` by the `setup` command.
|
**Agent Skill**: The markdown file bundled inside the npm package and installed to `~/.claude/skills/` by the `setup` command, or declared from the package by the [[home-manager module]].
|
||||||
_Avoid_: skill file, Claude skill
|
_Avoid_: skill file, Claude skill
|
||||||
|
|
||||||
**setup**: The explicit subcommand that installs the Agent Skill into `~/.claude/skills/`; gitea-axi's primary fulfillment of AXI Principle 7 (Ambient context).
|
**setup**: The explicit subcommand that installs the Agent Skill into `~/.claude/skills/`; gitea-axi's primary fulfillment of AXI Principle 7 (Ambient context).
|
||||||
Idempotent: re-running reports already-installed/updated rather than failing.
|
Idempotent: re-running reports already-installed/updated rather than failing.
|
||||||
There is no postinstall script — installation of the skill is always an explicit user action.
|
There is no postinstall script — installation of the skill is always an explicit user action.
|
||||||
`setup hooks` additionally opts into the [[SessionStart hook]].
|
`setup hooks` additionally opts into the [[SessionStart hook]].
|
||||||
|
It is the [[imperative install path]], and works only where the operator owns the target files; against a read-only target it reports the condition rather than writing.
|
||||||
_Avoid_: postinstall, installer script
|
_Avoid_: postinstall, installer script
|
||||||
|
|
||||||
**SessionStart hook**: An opt-in ambient-context mechanism installed by `setup hooks` via `axi-sdk-js`'s `installSessionStartHooks()` (Claude Code `settings.json`, Codex `hooks.json`, OpenCode plugin).
|
**SessionStart hook**: An opt-in ambient-context mechanism installed by `setup hooks` via `axi-sdk-js`'s `installSessionStartHooks()` (Claude Code `settings.json`, Codex `hooks.json`, OpenCode plugin), or declared by the [[home-manager module]].
|
||||||
It runs the bare `gitea-axi` binary (the short [[dashboard]] tier) in the session's working directory at session start and injects the output into the agent's context.
|
It runs the bare `gitea-axi` binary (the short [[dashboard]] tier) in the session's working directory at session start and injects the output into the agent's context.
|
||||||
The SDK's installer registers the binary with no arguments, so the hook always runs the short tier; outside a Gitea repo it produces the dashboard's `REPO_NOT_FOUND` error, an accepted noise trade-off.
|
The SDK's installer registers the binary with no arguments, so the hook always runs the short tier; outside a Gitea repo it produces the dashboard's `REPO_NOT_FOUND` error, an accepted noise trade-off.
|
||||||
|
The recorded command is currently the entrypoint's absolute path on any wrapper-based install, which rots whenever that path moves; recording the bare binary name and resolving it through `PATH` is agreed and lands with task 0043.
|
||||||
_Avoid_: session hook, ambient hook, postinstall hook
|
_Avoid_: session hook, ambient hook, postinstall hook
|
||||||
|
|
||||||
|
**imperative install path**: Installation of the Agent Skill and the [[SessionStart hook]] by running `setup`, which writes into the operator's agent configuration directory.
|
||||||
|
Requires the operator to own those files; a declaratively generated configuration renders them read-only and the command reports rather than writes.
|
||||||
|
Contrast the [[declarative install path]]. Both are supported and neither supersedes the other.
|
||||||
|
_Avoid_: manual install, imperative setup
|
||||||
|
|
||||||
|
**declarative install path**: Installation of the Agent Skill and the [[SessionStart hook]] by declaring them in a Nix configuration, which generates the agent configuration rather than mutating it.
|
||||||
|
Agreed and specified; the outputs it consumes land with task 0045.
|
||||||
|
Consumes the package's exposed Skill location and [[hook specification]], either directly or through the [[home-manager module]].
|
||||||
|
Chosen where the operator's agent configuration is generated and therefore read-only; contrast the [[imperative install path]].
|
||||||
|
_Avoid_: nix install, declarative setup
|
||||||
|
|
||||||
|
**home-manager module**: The flake output that declares the Agent Skill and the [[SessionStart hook]] from the package, as the [[declarative install path]]'s ergonomic front end (task 0045).
|
||||||
|
Importing it does nothing until enabled; it installs the package by default, with a null package the documented way to declare configuration without installing the binary, and carries a toggle per managed piece.
|
||||||
|
_Avoid_: nix module, HM module
|
||||||
|
|
||||||
|
**hook specification**: The single committed declaration of the [[SessionStart hook]]'s recorded shape — command, timeout, and matcher (task 0045).
|
||||||
|
Read by both the Nix expression and the test suite, so that the [[declarative install path]] and the [[imperative install path]] cannot disagree about what the hook is without failing a test.
|
||||||
|
_Avoid_: hook config, hook schema
|
||||||
|
|||||||
@@ -200,15 +200,30 @@ The workflow keeps its container-and-npm shape, deliberately preserving the GitH
|
|||||||
|
|
||||||
## Further Notes
|
## Further Notes
|
||||||
|
|
||||||
### Open verification item
|
### Resolved verification item: the hook records the absolute path under Nix
|
||||||
|
|
||||||
The `setup` command's hook installation passes the SDK both an absolute path to the running entrypoint and the bare binary name.
|
The `setup` command's hook installation passes the SDK both an absolute path to the running entrypoint and the bare binary name.
|
||||||
Under Nix the absolute path is content-addressed: it changes on every rebuild and is eventually garbage-collected, so a hook recording it would break silently, since a session-start hook that cannot execute simply does not run.
|
The design-time hope was that the SDK prefers search-path resolution and treats the absolute path as a fallback, which would have made this a non-issue.
|
||||||
The bare binary name strongly suggests the SDK prefers search-path resolution and treats the absolute path as a fallback, which would make this a non-issue, but this could not be confirmed during design because the dependency was not installed.
|
It was verified against the installed dependency and against a real Nix build, and the answer is the unfavourable one: **under Nix the absolute store path is recorded**, even with the binary on `PATH`.
|
||||||
|
|
||||||
The decision is to verify before acting.
|
The SDK's `resolvePortableHookCommand` returns the bare name only when some `PATH` entry *realpath-matches* the entrypoint, and the absolute path otherwise.
|
||||||
If the SDK does record the absolute path, the immediate mitigation is documenting that the hook setup should be re-run after an upgrade.
|
That test is what splits the two installation methods, and the split is a property of how each one puts the binary on `PATH`:
|
||||||
Changing the `setup` command to prefer the bare name would then become a separate task with its own ADR — justified on the grounds that a stable search-path name is more robust for *every* installation method, and explicitly not as a special case that detects Nix store paths in application code.
|
|
||||||
|
- **npm** symlinks the `bin` entry directly at the entrypoint, so the realpath comparison succeeds and the bare name is recorded.
|
||||||
|
- **Nix** installs the `bin` entry as a *generated wrapper script* that invokes `node <path>` — `nodejsInstallExecutables` inside `npmInstallHook`, plus this package's own `makeWrapper` layer for `git` and `tea`.
|
||||||
|
A wrapper's realpath is the wrapper, never the entrypoint, so the comparison cannot succeed and the absolute path is recorded.
|
||||||
|
|
||||||
|
So the preference for the bare name is real, but it is unreachable through any wrapper-based install.
|
||||||
|
It is not that Nix was overlooked; it is that the mechanism keys on a filesystem relationship only the symlink shape has.
|
||||||
|
|
||||||
|
The mitigation is therefore documentation, per the decision recorded when this item was opened: the `setup` command's help text states that `setup hooks` must be re-run after an upgrade.
|
||||||
|
The failure it guards against is silent — a session-start hook that cannot execute simply does not run, so a user gets no error, only the quiet absence of their ambient dashboard.
|
||||||
|
|
||||||
|
Changing the `setup` command to prefer the bare name remains a separate task with its own ADR, justified on the grounds that a stable search-path name is more robust for *every* installation method, and explicitly not as a special case that detects Nix store paths in application code.
|
||||||
|
Two findings feed that future task.
|
||||||
|
First, the mitigation above is documentation against a silent failure, which is the weakest kind of fix.
|
||||||
|
Second, a related defect shares the same line: `isManagedHook` recognises its own hook by testing whether the recorded command string *contains* the marker `gitea-axi`, so an entrypoint path lacking that substring makes `setup hooks` append a duplicate rather than update in place, contradicting the idempotency its help text promises.
|
||||||
|
That coupling is why `package.nix` renames its build tree in `postUnpack`; the rename can be deleted once the hook no longer depends on the entrypoint path.
|
||||||
|
|
||||||
### Verified during design
|
### Verified during design
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ Changing the `setup` command to prefer the bare name is explicitly **not** part
|
|||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [ ] The SDK's actual hook-path behavior is determined by observation against the installed dependency, not inference from its interface.
|
- [x] The SDK's actual hook-path behavior is determined by observation against the installed dependency, not inference from its interface.
|
||||||
- [ ] The finding is recorded where a future reader will meet it, so the question is not re-opened from scratch.
|
- [x] The finding is recorded where a future reader will meet it, so the question is not re-opened from scratch.
|
||||||
- [ ] If the absolute path is recorded, the documentation states that hook setup must be re-run after an upgrade.
|
- [x] If the absolute path is recorded, the documentation states that hook setup must be re-run after an upgrade.
|
||||||
- [ ] No change is made to how the `setup` command constructs the hook in this task.
|
- [x] No change is made to how the `setup` command constructs the hook in this task.
|
||||||
|
|
||||||
## Evidence gathered during task 0037
|
## Evidence gathered during task 0037
|
||||||
|
|
||||||
@@ -47,3 +47,52 @@ Consequences for this task:
|
|||||||
- Both defects trace to the same resolution line, so they should be weighed together.
|
- Both defects trace to the same resolution line, so they should be weighed together.
|
||||||
- The stale store path is user-facing breakage on the install method task 0037 added, which argues for not letting this drift far behind it.
|
- The stale store path is user-facing breakage on the install method task 0037 added, which argues for not letting this drift far behind it.
|
||||||
- `package.nix` carries a `postUnpack` rename of the build tree purely to work around the substring coupling. It is commented as a workaround and should be **deleted as part of this task**, once the hook no longer depends on the entrypoint path.
|
- `package.nix` carries a `postUnpack` rename of the build tree purely to work around the substring coupling. It is commented as a workaround and should be **deleted as part of this task**, once the hook no longer depends on the entrypoint path.
|
||||||
|
|
||||||
|
## Implementation Notes
|
||||||
|
|
||||||
|
### The observation
|
||||||
|
|
||||||
|
Task 0037's evidence was re-verified independently rather than taken on trust, since acceptance criterion 1 asks for observation and not for citation.
|
||||||
|
Two observations were made against the installed dependency.
|
||||||
|
|
||||||
|
A probe drove `resolvePortableHookCommand` directly with two synthetic install trees.
|
||||||
|
Given a `PATH` entry that is a *symlink* to the entrypoint it returned the bare name `gitea-axi`; given a `PATH` entry that is a *wrapper script* invoking `node <entrypoint>` it returned the absolute path.
|
||||||
|
Then the flake was built and the resulting binary driven for real against a temporary `HOME`.
|
||||||
|
With `$out/bin` on `PATH`, `~/.claude/settings.json` recorded:
|
||||||
|
|
||||||
|
```
|
||||||
|
/nix/store/pqxhyy5cg1rljyn78kxfpxyfpgz7rgzk-gitea-axi-0.1.0/lib/node_modules/gitea-axi/dist/main.js
|
||||||
|
```
|
||||||
|
|
||||||
|
This confirms 0037's finding and sharpens it.
|
||||||
|
The task framed the bare name as a hint that the SDK "prefers search-path resolution"; that preference is real, but it is gated on a `PATH` entry whose realpath equals the entrypoint.
|
||||||
|
npm satisfies that by symlinking its `bin` entry; Nix cannot, because `nodejsInstallExecutables` generates a wrapper script and this package adds a second `makeWrapper` layer for `git` and `tea`.
|
||||||
|
So the behaviour is not Nix-specific — it applies to *any* wrapper-based install — which strengthens the case, already recorded, that the eventual fix belongs in the `setup` command for every installation method rather than as a Nix special case.
|
||||||
|
|
||||||
|
### Deviations
|
||||||
|
|
||||||
|
**The `postUnpack` rename in `package.nix` was kept, not deleted.**
|
||||||
|
The "Evidence gathered during task 0037" section above says it "should be **deleted as part of this task**", which conflicts with acceptance criterion 4 and with the "What to build" section's statement that changing the hook to prefer the bare name is "explicitly **not** part of this task".
|
||||||
|
The conflict resolves on the Evidence section's own wording: the deletion is conditioned on "once the hook no longer depends on the entrypoint path", and establishing that precondition is exactly the out-of-scope change.
|
||||||
|
Deleting the rename now would leave the derivation's build tree at a path with no `gitea-axi` segment, which `isManagedHook`'s substring test still requires, and `test/setup.test.ts` would fail inside `checkPhase`.
|
||||||
|
The rename's comment was rewritten instead: it previously promised that task 0042 would remove the coupling, which would have become a stale forward reference the moment this task landed.
|
||||||
|
|
||||||
|
**The documentation surface is the `setup` help text.**
|
||||||
|
The repository has no README, so the command's own help is the only place a user meets this.
|
||||||
|
Criterion 4 is untouched — `binaryNames`, `execPath`, and the `installSessionStartHooks` call are all unchanged; only the `usage` string moved.
|
||||||
|
|
||||||
|
**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.
|
||||||
|
Leaving a statement the commit itself documents as untrue seemed worse than a one-line caveat, so the new paragraph notes that a stale entry may survive a re-run.
|
||||||
|
|
||||||
|
### Follow-up
|
||||||
|
|
||||||
|
The successor is task 0043, which covers both defects together — the absolute-path recording and `isManagedHook` recognising its hook by substring — since both trace to the same resolution line, and deletes `package.nix`'s `postUnpack` rename with them.
|
||||||
|
|
||||||
|
Grilling the mitigation afterwards found the framing here too narrow.
|
||||||
|
The maintainer's agent configuration is generated declaratively, so `~/.claude/settings.json` and the installed Skill are both read-only symlinks into the Nix store: `setup hooks` cannot write at all, and `setup` crashes outright on an unhandled filesystem error.
|
||||||
|
The recorded path's *shape* is therefore not the whole defect — the deeper one is that `setup` is write-only against a target that some operators cannot let it write.
|
||||||
|
Tasks 0044 and 0045 follow from that: a clean failure on unwritable targets, and a declarative install path that generates the configuration instead of mutating it.
|
||||||
|
|
||||||
|
The help-text mitigation added by this task is deliberately left in place rather than pre-emptively reverted.
|
||||||
|
It is accurate until task 0043 lands, which removes it as an acceptance criterion.
|
||||||
|
|||||||
34
.claude/tasks/0043-hook-records-bare-binary-name.md
Normal file
34
.claude/tasks/0043-hook-records-bare-binary-name.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
spec: nix-flake-packaging
|
||||||
|
---
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
Make the SessionStart hook survive an upgrade by recording a name that does not move.
|
||||||
|
|
||||||
|
Task 0042 established by observation that the hook records the entrypoint's absolute path on every wrapper-based install, and documented a re-run-after-upgrade mitigation.
|
||||||
|
This task removes the need for that mitigation.
|
||||||
|
|
||||||
|
The SDK returns the bare binary name only when a `PATH` entry realpath-matches the entrypoint it is handed.
|
||||||
|
An npm install satisfies that by symlinking its `bin` entry straight at the entrypoint; a wrapper-based install cannot, because a script that *invokes* a file never resolves *to* that file.
|
||||||
|
Handing the SDK the location where the binary actually resolves on `PATH`, rather than the module-relative entrypoint, makes the match succeed and the bare name get recorded — using the SDK's own resolution rather than bypassing it.
|
||||||
|
When the binary is not on `PATH` there is nothing to hand it, and the existing absolute-path behaviour stands unchanged as the fallback.
|
||||||
|
|
||||||
|
This is not a Nix accommodation.
|
||||||
|
Any wrapper-based install has the same shape — a shim, a launcher, a generated `.cmd` — and the fix is the convention for tools that write into user-owned configuration: prior art records a bare name and lets `PATH` resolve it, reserving absolute paths for configuration that a package manager regenerates.
|
||||||
|
|
||||||
|
A second defect shares the same line and is fixed here.
|
||||||
|
The hook is recognised as its own by testing whether the recorded command string *contains* the marker, so an entrypoint path lacking that substring makes re-running `setup hooks` append a duplicate rather than update in place, contradicting the idempotency its help text promises.
|
||||||
|
Recording the bare name makes the marker match by construction, but the recognition itself should not depend on the recorded command's shape.
|
||||||
|
|
||||||
|
The Nix derivation renames its build tree solely to work around that substring coupling.
|
||||||
|
Once the coupling is gone the rename has no remaining purpose and goes with it.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] The recorded hook command is the bare binary name whenever that name resolves to the running program on `PATH`.
|
||||||
|
- [ ] The recorded hook command remains the absolute entrypoint path when the binary is not resolvable on `PATH`, and that fallback is exercised by a test.
|
||||||
|
- [ ] Re-running `setup hooks` updates the existing entry in place rather than appending a second one, including when the entrypoint path does not contain the marker.
|
||||||
|
- [ ] The `setup` help text no longer instructs the user to re-run hooks after an upgrade, that instruction having become false.
|
||||||
|
- [ ] The derivation no longer renames its build tree, and the build still passes with the tree at a path that does not contain the marker.
|
||||||
|
- [ ] The behaviour is verified against a real wrapper-based install, not only against a source checkout.
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
spec: nix-flake-packaging
|
||||||
|
---
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
Report an unwritable target as an error the user can act on, instead of crashing.
|
||||||
|
|
||||||
|
Both halves of `setup` assume the files they manage are writable.
|
||||||
|
When they are not — because a configuration manager owns them, because a file is flagged immutable, because the path is root-owned — the skill install raises a raw filesystem error with no handling at all, and the hook install surfaces the underlying message through its error collector without saying what a reader should do about it.
|
||||||
|
|
||||||
|
Neither failure is exotic.
|
||||||
|
Any tool that manages a user's agent configuration declaratively renders these paths read-only, and gitea-axi's own Nix install method encourages exactly that arrangement.
|
||||||
|
|
||||||
|
The error names the file and the condition, and points at the general remedy: the file appears to be managed elsewhere, so the skill or hook should be declared through that configuration rather than installed by this command.
|
||||||
|
|
||||||
|
It deliberately does not guess at the cause.
|
||||||
|
Read-only is not diagnostic of any particular manager, and naming one would be wrong for most users who hit this.
|
||||||
|
|
||||||
|
The failure follows the CLI's existing error convention rather than inventing a shape, so it carries a code and help lines like every other error the tool reports.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] An unwritable skill target produces a structured CLI error rather than an unhandled filesystem exception.
|
||||||
|
- [ ] An unwritable hook target produces the same class of error, with the same guidance.
|
||||||
|
- [ ] Both errors name the file that could not be written and state that it appears to be managed by another tool.
|
||||||
|
- [ ] Neither error names or infers a specific configuration manager.
|
||||||
|
- [ ] A skill target that is unwritable but already byte-identical to the bundled copy succeeds rather than failing, since nothing needs to be written.
|
||||||
|
- [ ] The errors carry a code and help lines consistent with the rest of the CLI's error surface.
|
||||||
45
.claude/tasks/0045-declarative-nix-outputs-and-hm-module.md
Normal file
45
.claude/tasks/0045-declarative-nix-outputs-and-hm-module.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
spec: nix-flake-packaging
|
||||||
|
blocked-by: 0043-hook-records-bare-binary-name
|
||||||
|
---
|
||||||
|
|
||||||
|
## What to build
|
||||||
|
|
||||||
|
Let a Nix configuration declare gitea-axi's ambient context, instead of running a command that writes it.
|
||||||
|
|
||||||
|
`setup` and `setup hooks` are write-only.
|
||||||
|
They install the Agent Skill and the SessionStart hook by writing into the user's agent configuration directory, which works only when the user owns those files imperatively.
|
||||||
|
An operator whose agent configuration is generated declaratively cannot use either: the targets are read-only, and the operator is left hand-copying the Skill into their own configuration, where it silently drifts from the package that ships it.
|
||||||
|
|
||||||
|
The spec currently lists a home-manager module under Out of Scope, deferring it until there was usage evidence that the trade-off was worth making.
|
||||||
|
That evidence now exists, and the deferral's stated reasoning does not survive it: the concern was the automatism that ADR 0009 rejected when it chose an explicit `setup` command over a postinstall script, and a module the operator explicitly imports and enables is the opposite of an implicit install.
|
||||||
|
Revising that Out of Scope entry, and recording the decision as an ADR, is part of this task.
|
||||||
|
|
||||||
|
Two layers, the second built on the first.
|
||||||
|
|
||||||
|
The package gains a stable, documented location for the bundled Agent Skill, and exposes both the Skill and the hook's specification as attributes a Nix expression can consume.
|
||||||
|
Today the Skill's only address is a path inside the installed node modules tree, which is an implementation detail no consumer should depend on.
|
||||||
|
|
||||||
|
On top of that, the flake exposes a home-manager module: a thin wiring layer that declares the Skill and the hook from those attributes.
|
||||||
|
It follows the conventions the home-manager module tree overwhelmingly uses — an enable option so that importing the module does nothing until it is switched on, an overridable package option, and installation of that package by default with a null value as the documented opt-out for an operator who supplies the binary another way.
|
||||||
|
Each managed piece has its own toggle, defaulting on, so an operator can take the Skill declaratively while continuing to write the hook by hand.
|
||||||
|
|
||||||
|
The hook's specification is declared once, in a committed file that both the Nix expression and the test suite read.
|
||||||
|
Declaring it in the Nix expression alone would create a second source of truth alongside the behaviour of the imperative install path, with nothing to keep them agreed; a test that hardcoded the same values a third time would verify nothing.
|
||||||
|
The test drives the imperative install against a temporary home directory and asserts that what it writes matches what the file declares, so a divergence — including one introduced by the SDK changing the envelope it writes — fails a test rather than passing silently into a release.
|
||||||
|
|
||||||
|
The two installation paths remain independent and both supported: the command for operators who own their configuration, the module for operators whose configuration owns them.
|
||||||
|
|
||||||
|
## Acceptance criteria
|
||||||
|
|
||||||
|
- [ ] The bundled Agent Skill is installed to a stable location in the package output that is not an internal implementation path.
|
||||||
|
- [ ] The package exposes the Skill and the hook specification as attributes consumable from a Nix expression without building or running anything.
|
||||||
|
- [ ] The hook specification is declared in a single committed file, read by both the Nix expression and the test suite.
|
||||||
|
- [ ] A test drives the imperative hook install and asserts that what it writes matches the declared specification, failing if either side drifts.
|
||||||
|
- [ ] The flake exposes a home-manager module that declares the Skill and the hook.
|
||||||
|
- [ ] Importing the module without enabling it changes nothing about the resulting configuration.
|
||||||
|
- [ ] The module installs the package by default, and accepts a null package as the documented way to declare the configuration without installing the binary.
|
||||||
|
- [ ] The Skill and the hook each have their own toggle, both defaulting to on.
|
||||||
|
- [ ] The module composes with an existing configuration that already declares its own SessionStart hooks and skills, rather than conflicting with it.
|
||||||
|
- [ ] The spec's Out of Scope entry excluding a home-manager module is revised, and the decision to reverse it is recorded as an ADR.
|
||||||
|
- [ ] The user-facing documentation describes both installation paths and when each applies.
|
||||||
@@ -71,3 +71,9 @@ Its `act` fork declares `RawContinueOnError` on the `Step` struct only — `pkg/
|
|||||||
Gitea's own syntax-comparison page does not list the gap.
|
Gitea's own syntax-comparison page does not list the gap.
|
||||||
Put `continue-on-error` on each step instead: `act` and GitHub Actions both honour it there, and a job whose every step carries it concludes green on either platform.
|
Put `continue-on-error` on each step instead: `act` and GitHub Actions both honour it there, and a job whose every step carries it concludes green on either platform.
|
||||||
The same fork historically ignored `jobs.<id>.if` (go-gitea#25897), so treat any job-level key as needing a check against the fork's structs rather than against GitHub's documentation.
|
The same fork historically ignored `jobs.<id>.if` (go-gitea#25897), so treat any job-level key as needing a check against the fork's structs rather than against GitHub's documentation.
|
||||||
|
|
||||||
|
The session-start hook installed by `setup hooks` records the entrypoint's **absolute path**, not the bare binary name, on every wrapper-based install.
|
||||||
|
`resolvePortableHookCommand` in `axi-sdk-js` returns the bare name only when a `PATH` entry *realpath-matches* the entrypoint.
|
||||||
|
npm symlinks its `bin` entry straight at `dist/main.js`, so that match succeeds; Nix installs a generated wrapper script that invokes `node <path>`, whose realpath is the wrapper, so the match cannot succeed and the store path is recorded.
|
||||||
|
Passing `binaryNames` therefore does not make the hook portable under Nix — verify by driving the installed binary and reading `~/.claude/settings.json`, not by reading the SDK's interface.
|
||||||
|
The consequence is silent: a hook whose recorded path no longer exists does not run and does not warn.
|
||||||
|
|||||||
@@ -68,9 +68,12 @@ buildNpmPackage {
|
|||||||
# finding "gitea-axi" within it. Naming the tree makes the build representative
|
# finding "gitea-axi" within it. Naming the tree makes the build representative
|
||||||
# rather than an environment no operator ever has.
|
# rather than an environment no operator ever has.
|
||||||
#
|
#
|
||||||
# This coupling is a defect, not a property worth preserving — see task 0042,
|
# This coupling is a defect, not a property worth preserving. Task 0042
|
||||||
# which removes the hook's dependence on the entrypoint path entirely. Once it
|
# verified the resolution behaviour and documented the mitigation, but left
|
||||||
# lands this rename should go with it.
|
# the hook's dependence on the entrypoint path in place: removing it needs its
|
||||||
|
# own ADR, since a stable search-path name is the right answer for every
|
||||||
|
# installation method and not a Nix special case. This rename goes away with
|
||||||
|
# that task, not before.
|
||||||
postUnpack = ''
|
postUnpack = ''
|
||||||
mv "$sourceRoot" gitea-axi
|
mv "$sourceRoot" gitea-axi
|
||||||
export sourceRoot=gitea-axi
|
export sourceRoot=gitea-axi
|
||||||
|
|||||||
@@ -18,6 +18,14 @@ Install gitea-axi's ambient context for agent sessions.
|
|||||||
Both are idempotent: re-running updates the managed files in place rather than
|
Both are idempotent: re-running updates the managed files in place rather than
|
||||||
failing. There is no postinstall script — installation is always explicit.
|
failing. There is no postinstall script — installation is always explicit.
|
||||||
|
|
||||||
|
Re-run "setup hooks" after upgrading gitea-axi. The hook records an absolute
|
||||||
|
path to the entrypoint, which moves when the install location changes, and a
|
||||||
|
session-start hook that cannot be executed fails silently rather than warning.
|
||||||
|
This matters most for immutable installs such as Nix, where every rebuild lands
|
||||||
|
the entrypoint at a fresh path and the old one is eventually collected. When the
|
||||||
|
path moves, the re-run may leave the stale entry behind instead of replacing it;
|
||||||
|
remove it by hand if a duplicate appears.
|
||||||
|
|
||||||
flags:
|
flags:
|
||||||
--help Show this help
|
--help Show this help
|
||||||
`;
|
`;
|
||||||
|
|||||||
Reference in New Issue
Block a user