@codyswann/lisa 4.37.3 → 4.38.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/all/copy-contents/.gitattributes +9 -0
- package/all/copy-overwrite/scripts/lisa-work-item.mjs +209 -8
- package/dist/core/learnings-merge-driver.d.ts +8 -0
- package/dist/core/learnings-merge-driver.d.ts.map +1 -1
- package/dist/core/learnings-merge-driver.js +17 -0
- package/dist/core/learnings-merge-driver.js.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +6 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +37 -5
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +5 -4
- package/plugins/lisa/.claude-plugin/plugin.json +37 -1
- package/plugins/lisa/.codex-plugin/hooks.json +36 -0
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-git-submit-pr/SKILL.md +8 -3
- package/plugins/lisa/hooks/discharge-work-item-gates.sh +54 -0
- package/plugins/lisa/hooks/withdrawn-rulings.mjs +525 -0
- package/plugins/lisa/hooks/withdrawn-rulings.sh +24 -0
- package/plugins/lisa/rules/eager/withdrawn-rulings.md +69 -0
- package/plugins/lisa/rules/reference/withdrawn-rulings.md +114 -0
- package/plugins/lisa/skills/lisa-git-submit-pr/SKILL.md +8 -3
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-git-submit-pr/SKILL.md +8 -3
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +28 -1
- package/plugins/lisa-copilot/hooks/discharge-work-item-gates.sh +54 -0
- package/plugins/lisa-copilot/hooks/withdrawn-rulings.mjs +525 -0
- package/plugins/lisa-copilot/hooks/withdrawn-rulings.sh +24 -0
- package/plugins/lisa-copilot/rules/eager/withdrawn-rulings.md +69 -0
- package/plugins/lisa-copilot/rules/reference/withdrawn-rulings.md +114 -0
- package/plugins/lisa-copilot/skills/lisa-git-submit-pr/SKILL.md +8 -3
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/discharge-work-item-gates.sh +54 -0
- package/plugins/lisa-cursor/hooks/hooks.json +14 -0
- package/plugins/lisa-cursor/hooks/withdrawn-rulings.mjs +525 -0
- package/plugins/lisa-cursor/hooks/withdrawn-rulings.sh +24 -0
- package/plugins/lisa-cursor/rules/withdrawn-rulings-reference.mdc +119 -0
- package/plugins/lisa-cursor/rules/withdrawn-rulings.mdc +74 -0
- package/plugins/lisa-cursor/skills/lisa-git-submit-pr/SKILL.md +8 -3
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/.claude-plugin/plugin.json +36 -0
- package/plugins/src/base/hooks/discharge-work-item-gates.sh +54 -0
- package/plugins/src/base/hooks/withdrawn-rulings.mjs +525 -0
- package/plugins/src/base/hooks/withdrawn-rulings.sh +24 -0
- package/plugins/src/base/rules/eager/withdrawn-rulings.md +69 -0
- package/plugins/src/base/rules/reference/withdrawn-rulings.md +114 -0
- package/plugins/src/base/skills/lisa-git-submit-pr/SKILL.md +8 -3
- package/scripts/lib/hook-registration-audit.mjs +612 -0
- package/scripts/lib/per-agent-hook-filter.mjs +19 -0
- package/typescript/copy-contents/.husky/pre-push +98 -26
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Withdrawn Rulings — reference
|
|
2
|
+
|
|
3
|
+
Long-form body for the eager rule `withdrawn-rulings`. Origin: CodySwannGT/lisa#3752.
|
|
4
|
+
|
|
5
|
+
## The general property
|
|
6
|
+
|
|
7
|
+
A session is a snapshot. Three independent instances of it were measured on one day:
|
|
8
|
+
|
|
9
|
+
1. **Plugin version.** A session executes the plugin cache directory resolved *when the session
|
|
10
|
+
started*. A session roughly eleven hours old was running one version while the default branch and
|
|
11
|
+
the marketplace clone were two releases ahead — with the newer version already sitting in that
|
|
12
|
+
cache. Not a distribution failure: updating the cache does not help a running session, only a
|
|
13
|
+
restart re-resolves. That session reported an already-fixed defect as live, persuasively, because
|
|
14
|
+
it really had observed the behaviour. It was reporting the truth about a stale binary.
|
|
15
|
+
2. **Rules injection.** The rule injector reads `rules/eager/*.md` and concatenates them into
|
|
16
|
+
context at SessionStart and SubagentStart. No metadata, no expiry, no filter — a rule withdrawn
|
|
17
|
+
upstream stays in the context of every session that started before the withdrawal, for that
|
|
18
|
+
session's whole life.
|
|
19
|
+
3. **Shipped versus in effect.** A fix merged to the default branch is not in effect for any session
|
|
20
|
+
already running.
|
|
21
|
+
|
|
22
|
+
**A fix has two facts behind it: that it exists, and that it is in effect.** Testing either one and
|
|
23
|
+
reporting "fixed" is the error. Two agents made opposite halves of that mistake in a single evening,
|
|
24
|
+
neither carelessly, each holding a real measurement.
|
|
25
|
+
|
|
26
|
+
## The two instances that produced this rule
|
|
27
|
+
|
|
28
|
+
**A correction that was itself wrong, published.** A claim was refuted with specific file-and-line
|
|
29
|
+
evidence. The refutation was propagated to two agents and into a public work-item comment before a
|
|
30
|
+
third agent, reading the source directly, established that the original claim was right and the
|
|
31
|
+
refutation had been produced by grepping a stale checkout. The wrong correction stood for roughly
|
|
32
|
+
forty minutes. Anyone who read that item in the interval holds the wrong version and has no signal
|
|
33
|
+
it changed — the retraction is a later comment, which a reader who has already formed a conclusion
|
|
34
|
+
will not necessarily see.
|
|
35
|
+
|
|
36
|
+
**A workaround circulated, then retracted.** A technique was recommended to three agents, then
|
|
37
|
+
disproved by measurement and withdrawn. The three had no mechanism to learn it was withdrawn.
|
|
38
|
+
|
|
39
|
+
And the technique had **zero observed successes but still read as having worked**: the agent
|
|
40
|
+
performed it, the very next operation was refused, it worked around the failure by other means, and
|
|
41
|
+
later the condition the technique was supposed to create arrived on its own for unrelated reasons.
|
|
42
|
+
Nothing about that sequence looks like a failure from outside.
|
|
43
|
+
|
|
44
|
+
## Why durable memory is the worst case
|
|
45
|
+
|
|
46
|
+
A superseded finding survives longest exactly where it was best recorded. A claim made in passing
|
|
47
|
+
decays with the conversation; a claim written to a memory file persists and is re-read
|
|
48
|
+
authoritatively by future sessions. **The more responsibly a finding was captured, the more durable
|
|
49
|
+
its error becomes** — and the retraction, being conversational, decays while the claim does not.
|
|
50
|
+
|
|
51
|
+
## What makes this hard
|
|
52
|
+
|
|
53
|
+
- **A session cannot detect that its own context is stale.** Context completeness is not observable
|
|
54
|
+
from inside. Any fix that asks an agent to assess its own context is the trap, not the remedy.
|
|
55
|
+
- **A retraction is usually not written to any canonical surface.** It is a reply, produced under
|
|
56
|
+
exactly the conditions least likely to bear a chore.
|
|
57
|
+
- **The audience is not enumerable.** Whoever received the original may have relayed it onward, and
|
|
58
|
+
a session that has gone quiet is unreachable by any message.
|
|
59
|
+
|
|
60
|
+
The third point is why the mechanism is a **re-check by the reader**, not a broadcast by the
|
|
61
|
+
publisher. The publisher records once; every live session re-checks on its own.
|
|
62
|
+
|
|
63
|
+
## The ledger's two tiers
|
|
64
|
+
|
|
65
|
+
| tier | path | who it reaches |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| repository | `.lisa/WITHDRAWN.jsonl` (committed, union-merged) | every future reader of this project, forever |
|
|
68
|
+
| machine | `${LISA_STATE_HOME:-~/.lisa}/withdrawn-rulings.jsonl` | sibling sessions in **other worktrees on this machine, now** |
|
|
69
|
+
|
|
70
|
+
A withdrawal is written to both by one command; reads are the union, de-duplicated by id. The
|
|
71
|
+
machine tier exists because a committed file cannot reach a sibling agent until it is merged and
|
|
72
|
+
pulled, and the audience that needs the retraction soonest is the one working beside you.
|
|
73
|
+
|
|
74
|
+
JSONL rather than prose: each line is independent, so concurrent appends from many agents do not
|
|
75
|
+
collide and `merge=union` reconstructs the union exactly. A prose ledger would need a bespoke merge
|
|
76
|
+
driver to survive the same traffic.
|
|
77
|
+
|
|
78
|
+
## How a running session is reached
|
|
79
|
+
|
|
80
|
+
`--session-start` stamps a per-session mark recording the ids the session was born already knowing.
|
|
81
|
+
`--hook` runs after every tool result and announces exactly the entries that appeared **since**,
|
|
82
|
+
once each.
|
|
83
|
+
|
|
84
|
+
The common case is the cheap case: when neither ledger's `size:mtime` has moved, `--hook` returns
|
|
85
|
+
after two `stat` calls without parsing anything. It fires on every tool call in every session and
|
|
86
|
+
every subagent, so anything expensive multiplies.
|
|
87
|
+
|
|
88
|
+
A **missing mark is deliberately silent**. A session with no mark is one whose starting knowledge is
|
|
89
|
+
unknown; announcing every historical withdrawal to it would degrade the mechanism into distrusting
|
|
90
|
+
everything, which is the failure the control case in #3752 exists to prevent.
|
|
91
|
+
|
|
92
|
+
## Surface parity
|
|
93
|
+
|
|
94
|
+
| surface | session stamp | mid-session announcement | `--list` at the escalation boundary |
|
|
95
|
+
|---|---|---|---|
|
|
96
|
+
| Claude Code | yes — SessionStart and SubagentStart | yes — PostToolUse | yes |
|
|
97
|
+
| Codex | yes, interactive only | yes, interactive only | yes |
|
|
98
|
+
| Cursor | yes — both start events | yes | yes |
|
|
99
|
+
| Copilot | main sessions only — it has no subagent-start event, so a Copilot subagent is stamp-less and therefore silent | yes — `postToolUse` | yes |
|
|
100
|
+
| Antigravity | no — its plugin ships blocking `PreToolUse` guards only, and headless hooks do not fire | no | yes |
|
|
101
|
+
| OpenCode | no — it has no plugin hook runtime, only rules and skills | no | yes |
|
|
102
|
+
|
|
103
|
+
Where a surface cannot carry the automatic half, the eager rule's `--list` instruction is the
|
|
104
|
+
carried half: it is the same pointer shape #3592 shipped, which survives precisely because it does
|
|
105
|
+
not travel inside the thing it points at. `codex exec` runs no plugin hooks at all, so on that
|
|
106
|
+
surface the ledger is a read the agent performs, not one performed for it. Antigravity and OpenCode
|
|
107
|
+
are the same shape, permanently rather than per-invocation: neither carries a session-lifecycle hook
|
|
108
|
+
today, which is the identical accommodation `failure-signature-index` makes on those two surfaces.
|
|
109
|
+
|
|
110
|
+
## What deliberately does not belong here
|
|
111
|
+
|
|
112
|
+
A disagreement that has not been settled. The ledger is for a claim its own author has **withdrawn**
|
|
113
|
+
— not for a claim someone doubts. A tombstone for a live dispute converts the ledger into an
|
|
114
|
+
argument, and an argument is not something a session can act on in one line.
|
|
@@ -57,6 +57,7 @@ Add provider-appropriate linkage to the PR title and/or body without changing th
|
|
|
57
57
|
- **GitHub Issues**:
|
|
58
58
|
- If `work_item_ref` is a GitHub issue URL, `org/repo#<n>`, or `#<n>`, add a dedicated issue reference line to the PR body.
|
|
59
59
|
- Always use a non-closing reference such as `Refs #<n>`, so the merge cannot close the issue before the post-merge deploy, remote verification, health check, and terminal `done` label.
|
|
60
|
+
- **This rule is what makes the managed backlink mandatory, and neither rule says so on its own.** `Refs` creates no native development link, so gate 5 has nothing to defer to and the `[lisa-pr-link]` comment becomes the only backlink there is. Anyone following the non-closing rule alone will hit gate 5. Separately, `Refs #<n>` does **not** satisfy gate 4 either: the body needs its own `Work-Item: <ref>` line, and `Closes`/`Fixes` do not satisfy it. One `Refs` line, one `Work-Item:` line, one backlink comment — three different requirements that look like one. `discharge-pr-gates` (below) is what checks the last two together.
|
|
60
61
|
- **A non-closing reference does not populate the issue's Development / linked pull requests surface, and no non-closing form does.** That surface *is* the closing-reference mechanism: a closing keyword populates the PR's `closingIssuesReferences`, while `Refs` yields only a `CrossReferencedEvent`. Measured on this repository — a `Refs`-only PR reports `closingIssuesReferences: 0`; a `Closes` PR reports 1. So the ticket-side backlink cannot be delegated to GitHub: the managed `[lisa-pr-link]` comment written by `node scripts/lisa-work-item.mjs backlink` — the one producer, which `lisa-github-sync` and the other vendor sync skills call rather than reimplement — is the **required** backlink under this rule, not a fallback for when native linkage happens to be absent. Two-way linkage (`lisa-implement` step 7a) depends on that comment, and so does the Work-Item Traceability check wherever the project declares `workItem.verify: "full"` — there, a PR carrying a correct `Refs` line still fails the check without it. Post it either way: under the default `trailer` level the check does not read the tracker, but the two-way linkage a human follows is still worth having, and a project can raise its level at any time.
|
|
61
62
|
- For cross-repo issue refs, use the fully qualified non-closing form, for example `Refs CodySwannGT/lisa#614`.
|
|
62
63
|
- **Linear**:
|
|
@@ -76,13 +77,17 @@ When updating an existing PR, preserve any existing linkage line unless the new
|
|
|
76
77
|
After creating or updating the PR, always make the reverse link durable on the source work item when `work_item_ref` is available:
|
|
77
78
|
|
|
78
79
|
1. Resolve the live PR URL with `gh pr view <pr-number> --json url --jq .url`.
|
|
79
|
-
2.
|
|
80
|
+
2. Discharge the two gates the push could not check. Gate 4 (the `Work-Item:` line in the PR BODY) and gate 5 (the backlink) are both properties of a pull request, so a push before the PR existed reported them as `UNRESOLVED` rather than checked. One command closes both out at the first moment they *are* checkable:
|
|
80
81
|
|
|
81
82
|
```bash
|
|
82
|
-
node scripts/lisa-work-item.mjs
|
|
83
|
+
node scripts/lisa-work-item.mjs discharge-pr-gates
|
|
83
84
|
```
|
|
84
85
|
|
|
85
|
-
It
|
|
86
|
+
It posts (or refreshes) the managed `[lisa-pr-link]` comment on every item the range names — so gate 5 passes without anyone remembering to — and then evaluates gate 4 against the live body, failing here rather than one CI cycle later. Exit 3 means there is no pull request for this branch yet, which is not a violation; exit 1 is a real unmet requirement and the message names it.
|
|
87
|
+
|
|
88
|
+
It writes no PR body. Gate 4 is the author's declaration of what the change is for; a command that inserted the line would be answering its own question.
|
|
89
|
+
|
|
90
|
+
The narrower `node scripts/lisa-work-item.mjs backlink --ref <work_item_ref> --pr-url <url>` is what it wraps, and remains the right call when you hold a ref and a URL but no checkout of the PR's branch (a sync skill updating a backlink after the fact). Both are idempotent, refuse loudly for a tracker they cannot write, and never silently no-op. Do not hand-post the comment, and do not describe the posting procedure anywhere: the same file that writes it is the file that checks it, which is what keeps producer and consumer from drifting.
|
|
86
91
|
3. Invoke `lisa-tracker-sync` with the original work item ref, milestone `pr-ready`, `pr_url=<url>`, and `tracker_provider=<provider>` when known. That is the progress-note and status side; it is not what satisfies the traceability check.
|
|
87
92
|
4. When the PR later merges, invoke `lisa-tracker-sync` again with milestone `pr-merged`, the same `pr_url`, and the merge SHA when available.
|
|
88
93
|
|
|
@@ -57,6 +57,7 @@ Add provider-appropriate linkage to the PR title and/or body without changing th
|
|
|
57
57
|
- **GitHub Issues**:
|
|
58
58
|
- If `work_item_ref` is a GitHub issue URL, `org/repo#<n>`, or `#<n>`, add a dedicated issue reference line to the PR body.
|
|
59
59
|
- Always use a non-closing reference such as `Refs #<n>`, so the merge cannot close the issue before the post-merge deploy, remote verification, health check, and terminal `done` label.
|
|
60
|
+
- **This rule is what makes the managed backlink mandatory, and neither rule says so on its own.** `Refs` creates no native development link, so gate 5 has nothing to defer to and the `[lisa-pr-link]` comment becomes the only backlink there is. Anyone following the non-closing rule alone will hit gate 5. Separately, `Refs #<n>` does **not** satisfy gate 4 either: the body needs its own `Work-Item: <ref>` line, and `Closes`/`Fixes` do not satisfy it. One `Refs` line, one `Work-Item:` line, one backlink comment — three different requirements that look like one. `discharge-pr-gates` (below) is what checks the last two together.
|
|
60
61
|
- **A non-closing reference does not populate the issue's Development / linked pull requests surface, and no non-closing form does.** That surface *is* the closing-reference mechanism: a closing keyword populates the PR's `closingIssuesReferences`, while `Refs` yields only a `CrossReferencedEvent`. Measured on this repository — a `Refs`-only PR reports `closingIssuesReferences: 0`; a `Closes` PR reports 1. So the ticket-side backlink cannot be delegated to GitHub: the managed `[lisa-pr-link]` comment written by `node scripts/lisa-work-item.mjs backlink` — the one producer, which `lisa-github-sync` and the other vendor sync skills call rather than reimplement — is the **required** backlink under this rule, not a fallback for when native linkage happens to be absent. Two-way linkage (`lisa-implement` step 7a) depends on that comment, and so does the Work-Item Traceability check wherever the project declares `workItem.verify: "full"` — there, a PR carrying a correct `Refs` line still fails the check without it. Post it either way: under the default `trailer` level the check does not read the tracker, but the two-way linkage a human follows is still worth having, and a project can raise its level at any time.
|
|
61
62
|
- For cross-repo issue refs, use the fully qualified non-closing form, for example `Refs CodySwannGT/lisa#614`.
|
|
62
63
|
- **Linear**:
|
|
@@ -76,13 +77,17 @@ When updating an existing PR, preserve any existing linkage line unless the new
|
|
|
76
77
|
After creating or updating the PR, always make the reverse link durable on the source work item when `work_item_ref` is available:
|
|
77
78
|
|
|
78
79
|
1. Resolve the live PR URL with `gh pr view <pr-number> --json url --jq .url`.
|
|
79
|
-
2.
|
|
80
|
+
2. Discharge the two gates the push could not check. Gate 4 (the `Work-Item:` line in the PR BODY) and gate 5 (the backlink) are both properties of a pull request, so a push before the PR existed reported them as `UNRESOLVED` rather than checked. One command closes both out at the first moment they *are* checkable:
|
|
80
81
|
|
|
81
82
|
```bash
|
|
82
|
-
node scripts/lisa-work-item.mjs
|
|
83
|
+
node scripts/lisa-work-item.mjs discharge-pr-gates
|
|
83
84
|
```
|
|
84
85
|
|
|
85
|
-
It
|
|
86
|
+
It posts (or refreshes) the managed `[lisa-pr-link]` comment on every item the range names — so gate 5 passes without anyone remembering to — and then evaluates gate 4 against the live body, failing here rather than one CI cycle later. Exit 3 means there is no pull request for this branch yet, which is not a violation; exit 1 is a real unmet requirement and the message names it.
|
|
87
|
+
|
|
88
|
+
It writes no PR body. Gate 4 is the author's declaration of what the change is for; a command that inserted the line would be answering its own question.
|
|
89
|
+
|
|
90
|
+
The narrower `node scripts/lisa-work-item.mjs backlink --ref <work_item_ref> --pr-url <url>` is what it wraps, and remains the right call when you hold a ref and a URL but no checkout of the PR's branch (a sync skill updating a backlink after the fact). Both are idempotent, refuse loudly for a tracker they cannot write, and never silently no-op. Do not hand-post the comment, and do not describe the posting procedure anywhere: the same file that writes it is the file that checks it, which is what keeps producer and consumer from drifting.
|
|
86
91
|
3. Invoke `lisa-tracker-sync` with the original work item ref, milestone `pr-ready`, `pr_url=<url>`, and `tracker_provider=<provider>` when known. That is the progress-note and status side; it is not what satisfies the traceability check.
|
|
87
92
|
4. When the PR later merges, invoke `lisa-tracker-sync` again with milestone `pr-merged`, the same `pr_url`, and the merge SHA when available.
|
|
88
93
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.38.1",
|
|
4
4
|
"description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -36,6 +36,15 @@
|
|
|
36
36
|
}
|
|
37
37
|
]
|
|
38
38
|
},
|
|
39
|
+
{
|
|
40
|
+
"matcher": "Bash",
|
|
41
|
+
"hooks": [
|
|
42
|
+
{
|
|
43
|
+
"type": "command",
|
|
44
|
+
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/discharge-work-item-gates.sh"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
39
48
|
{
|
|
40
49
|
"matcher": "Edit|Write|NotebookEdit|Bash",
|
|
41
50
|
"hooks": [
|
|
@@ -44,6 +53,15 @@
|
|
|
44
53
|
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/threshold-ratchet.sh"
|
|
45
54
|
}
|
|
46
55
|
]
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"matcher": "Bash|Edit|Write|Read|Task|Grep|Glob",
|
|
59
|
+
"hooks": [
|
|
60
|
+
{
|
|
61
|
+
"type": "command",
|
|
62
|
+
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/withdrawn-rulings.sh --hook"
|
|
63
|
+
}
|
|
64
|
+
]
|
|
47
65
|
}
|
|
48
66
|
],
|
|
49
67
|
"preToolUse": [
|
|
@@ -129,6 +147,15 @@
|
|
|
129
147
|
}
|
|
130
148
|
]
|
|
131
149
|
},
|
|
150
|
+
{
|
|
151
|
+
"matcher": "",
|
|
152
|
+
"hooks": [
|
|
153
|
+
{
|
|
154
|
+
"type": "command",
|
|
155
|
+
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/withdrawn-rulings.sh --session-start"
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
},
|
|
132
159
|
{
|
|
133
160
|
"matcher": "",
|
|
134
161
|
"hooks": [
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# This file is managed by Lisa.
|
|
3
|
+
# Do not edit directly — changes will be overwritten on the next `lisa` run.
|
|
4
|
+
# =============================================================================
|
|
5
|
+
# Discharge Deferred Work-Item Gates Hook (PostToolUse - Bash)
|
|
6
|
+
# =============================================================================
|
|
7
|
+
# Two of the five Work-Item Traceability gates live OUTSIDE the commits: gate 4
|
|
8
|
+
# is the `Work-Item:` line in the pull-request BODY, and gate 5 is the managed
|
|
9
|
+
# `[lisa-pr-link]` backlink on the item. A push cannot check either one —
|
|
10
|
+
# both are properties of a pull request, and the push is what makes the pull
|
|
11
|
+
# request possible — so until this hook existed the next thing that looked was
|
|
12
|
+
# CI, one cycle later (CodySwannGT/lisa#3791).
|
|
13
|
+
#
|
|
14
|
+
# This fires the moment a pull request is created or its body edited, which is
|
|
15
|
+
# the FIRST moment both gates are checkable. It evaluates them, and posts the
|
|
16
|
+
# backlink that gate 5 needs, so neither waits for a red CI run to be revealed.
|
|
17
|
+
#
|
|
18
|
+
# Exit 2 blocks and hands the output back to the agent, which is the point: a
|
|
19
|
+
# non-blocking notice here would be the same defect the discharge exists to
|
|
20
|
+
# fix — a finding delivered somewhere nobody has to act on it.
|
|
21
|
+
# =============================================================================
|
|
22
|
+
set -uo pipefail
|
|
23
|
+
|
|
24
|
+
JSON_INPUT="$(cat)"
|
|
25
|
+
|
|
26
|
+
command -v jq >/dev/null 2>&1 || exit 0
|
|
27
|
+
command -v node >/dev/null 2>&1 || exit 0
|
|
28
|
+
|
|
29
|
+
COMMAND="$(printf '%s' "$JSON_INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null || true)"
|
|
30
|
+
[ -n "$COMMAND" ] || exit 0
|
|
31
|
+
|
|
32
|
+
# `gh pr create` opens one; `gh pr edit` is the other way a body comes to carry
|
|
33
|
+
# — or lose — its declaration. Both change the answer to gate 4.
|
|
34
|
+
case "$COMMAND" in
|
|
35
|
+
*"gh pr create"* | *"gh pr edit"*) ;;
|
|
36
|
+
*) exit 0 ;;
|
|
37
|
+
esac
|
|
38
|
+
|
|
39
|
+
repo_root="$(git rev-parse --show-toplevel 2>/dev/null)" || exit 0
|
|
40
|
+
[ -f "$repo_root/scripts/lisa-work-item.mjs" ] || exit 0
|
|
41
|
+
|
|
42
|
+
output="$(cd "$repo_root" && node scripts/lisa-work-item.mjs discharge-pr-gates 2>&1)"
|
|
43
|
+
status=$?
|
|
44
|
+
|
|
45
|
+
# 0 is a clean discharge. 3 is the validator's own answer for "no pull request
|
|
46
|
+
# to check yet", which PostToolUse reaches on every `gh pr create` that FAILED
|
|
47
|
+
# — the tool call still ran, so the hook still fires. Collapsing 3 into the
|
|
48
|
+
# blocking arm would report a work-item violation on somebody's typo.
|
|
49
|
+
case "$status" in
|
|
50
|
+
0 | 3) exit 0 ;;
|
|
51
|
+
esac
|
|
52
|
+
|
|
53
|
+
printf '%s\n' "$output" >&2
|
|
54
|
+
exit 2
|