@codyswann/lisa 3.42.0 → 3.43.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.
Files changed (65) hide show
  1. package/all/copy-overwrite/scripts/lisa-work-item.mjs +203 -1
  2. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  3. package/dist/core/lisa-owned-hash-ledger.js +2 -0
  4. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  5. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  6. package/dist/core/upstream-evidence-manifest.js +4 -3
  7. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  8. package/expo/create-only/.github/workflows/playwright-e2e.yml +27 -4
  9. package/package.json +1 -1
  10. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  11. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  12. package/plugins/lisa/.codex-plugin/skills/lisa-drive-pr-to-merge/SKILL.md +50 -0
  13. package/plugins/lisa/skills/lisa-drive-pr-to-merge/SKILL.md +50 -0
  14. package/plugins/lisa-agy/plugin.json +1 -1
  15. package/plugins/lisa-agy/skills/lisa-drive-pr-to-merge/SKILL.md +50 -0
  16. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  17. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  18. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  19. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  20. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-copilot/skills/lisa-drive-pr-to-merge/SKILL.md +50 -0
  23. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-cursor/skills/lisa-drive-pr-to-merge/SKILL.md +50 -0
  25. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  27. package/plugins/lisa-expo-agy/plugin.json +1 -1
  28. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  32. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  33. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  37. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  38. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  42. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  43. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  47. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  48. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  52. package/plugins/lisa-rails-agy/plugin.json +1 -1
  53. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  57. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  58. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  62. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  63. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  65. package/plugins/src/base/skills/lisa-drive-pr-to-merge/SKILL.md +50 -0
@@ -31,6 +31,11 @@ name: 🎭 Playwright Web E2E
31
31
  # }
32
32
  # }
33
33
  #
34
+ # READ THE SHARDING NOTE BELOW BEFORE DECLARING IT AT THIS MOMENT. Declaring the
35
+ # gate `required` here is NOT free: it moves the suite off the shard matrix onto
36
+ # a single runner. That is a real trade, and for a suite of any size it is
37
+ # usually the wrong one — see "SHARDING" below for what actually happens.
38
+ #
34
39
  # The gate's task is `test:e2e`, so the project needs that script in
35
40
  # package.json — Lisa resolves the PROPERTY ("browser journeys pass end to
36
41
  # end"), never the tool.
@@ -91,6 +96,14 @@ on:
91
96
  # visible way to stop requiring a check — as opposed to a job that silently
92
97
  # stops running. Nothing inside this file can enforce it; the only defence is
93
98
  # that whoever seeds it knows.
99
+ #
100
+ # **`pull-request: off` ALONE is enough to stop the duplicate run**, and it is
101
+ # what most projects should write. The `continuous:*` half above is shown for
102
+ # completeness, not as a recommendation: declaring the gate at the nightly
103
+ # moment costs you the shard matrix. If this project's suite takes long enough
104
+ # to shard, declare `off` at `pull-request` and leave the nightly moment
105
+ # UNDECLARED — an undeclared gate keeps Lisa's built-in sharded run, which is
106
+ # the behaviour you already have.
94
107
 
95
108
  permissions:
96
109
  contents: read
@@ -143,10 +156,20 @@ jobs:
143
156
  # out; that is a visible decision, which a silent skip is not.
144
157
  prepare_environment: 'development'
145
158
  prepare_verbs: 'reset,reseed'
146
- # Applies only while `e2e-browser` is undeclared: Lisa cannot append
147
- # `--shard` to a command whose shape it does not know, and the `--`
148
- # passthrough differs between npm, yarn and bun. A declared gate runs on
149
- # one runner; shard inside the project's own `test:e2e` script instead.
159
+ # Applies only while `e2e-browser` is undeclared at THIS workflow's
160
+ # moment. Lisa cannot append `--shard` to a command whose shape it does
161
+ # not know, and the `--` passthrough differs between npm, yarn and bun.
162
+ #
163
+ # The consequence is bigger than it sounds and it is silent: once the
164
+ # gate resolves to a task, EVERY shard concludes "Shard idle — the
165
+ # e2e-browser gate owns this suite" and the aggregate job runs the whole
166
+ # suite by itself. A four-shard nightly becomes a one-runner nightly with
167
+ # no error and no warning, while still holding whatever concurrency group
168
+ # the other suites join. Measured on a consumer whose ~25-minute sharded
169
+ # suite would have become a single serial run.
170
+ #
171
+ # So: shard inside the project's own `test:e2e` script if you declare the
172
+ # gate here, or leave this moment undeclared and keep the matrix.
150
173
  playwright_shards: 2
151
174
  # Leave false unless the cache key has been checked against this project's
152
175
  # layout. Lisa's key is a fingerprint of build inputs, and a key that
package/package.json CHANGED
@@ -132,7 +132,7 @@
132
132
  "ws": ">=8.21.0"
133
133
  },
134
134
  "name": "@codyswann/lisa",
135
- "version": "3.42.0",
135
+ "version": "3.43.1",
136
136
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
137
137
  "main": "dist/index.js",
138
138
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -470,6 +470,56 @@ matching Phase 4b's safe default. The full procedure is `lisa-linear-sync`
470
470
  Phase 4b; when the caller's flow already runs a `pr-merged` sync for this
471
471
  merge, confirming that sync ran satisfies this step.
472
472
 
473
+ ### d. Complete the work item
474
+
475
+ Run this once the PR reports `MERGED` and the ancestry check has passed:
476
+
477
+ ```
478
+ node scripts/lisa-work-item.mjs complete --ref <work-item>
479
+ ```
480
+
481
+ resolving the script the usual three ways (installed package, host `scripts/`,
482
+ this repo's own tree).
483
+
484
+ **This step exists because the previous arrangement did not work, measured.**
485
+ The instruction to move a work item to its terminal role lived in
486
+ `lisa-git-submit-pr`, in a section reached *after* that skill delegates the
487
+ entire merge loop to this one. So the skill that observes the merge was never
488
+ told to close anything, and the skill that was told had already handed off. The
489
+ result: **27 of 27** open items carrying the claimed role in this repository had
490
+ a merged pull request — the claimed lane reported 27 things in flight when the
491
+ real number was one.
492
+
493
+ Three properties make the command safe to run unconditionally:
494
+
495
+ 1. **The terminal role is RESOLVED, never assumed.** `lifecycleContract` reads
496
+ `github.labels.build.done` (or the Jira/Linear equivalent), which is
497
+ environment-aware — a repository whose target is `dev` has a different
498
+ terminal role than one merging to production, and a hardcoded label would
499
+ apply the wrong one while looking correct in the repository it was written
500
+ in.
501
+ 2. **It refuses without evidence.** Completion requires a merged pull request in
502
+ the same repository. A command that closes whatever it is pointed at is a way
503
+ to make unfinished work disappear, and the closure is indistinguishable from
504
+ a real one afterwards. Cross-repository references do not count: a downstream
505
+ consumer's PR mentioning an upstream issue is not evidence the upstream issue
506
+ shipped.
507
+ 3. **It is idempotent**, so re-running after a retry converges rather than
508
+ accumulating.
509
+
510
+ It also removes the claimed role rather than only adding the terminal one.
511
+ Leaving both produces exactly the drift this step exists to end — an item that
512
+ is closed *and* still reports as in progress.
513
+
514
+ If the command refuses, do not close by hand. A refusal means the evidence is
515
+ not there, and a lifecycle step performed by hand is one nothing can verify
516
+ happened.
517
+
518
+ **The backstop, for the ones that still slip:** `lisa-work-item.mjs sweep`
519
+ reports every claimed item that already has a merged pull request, and
520
+ `--apply` completes them. Reporting is the default deliberately — a sweep that
521
+ closes things as a side effect of being run is not one anyone runs twice.
522
+
473
523
  ## 4. Terminal states
474
524
 
475
525
  Loop until one of:
@@ -470,6 +470,56 @@ matching Phase 4b's safe default. The full procedure is `lisa-linear-sync`
470
470
  Phase 4b; when the caller's flow already runs a `pr-merged` sync for this
471
471
  merge, confirming that sync ran satisfies this step.
472
472
 
473
+ ### d. Complete the work item
474
+
475
+ Run this once the PR reports `MERGED` and the ancestry check has passed:
476
+
477
+ ```
478
+ node scripts/lisa-work-item.mjs complete --ref <work-item>
479
+ ```
480
+
481
+ resolving the script the usual three ways (installed package, host `scripts/`,
482
+ this repo's own tree).
483
+
484
+ **This step exists because the previous arrangement did not work, measured.**
485
+ The instruction to move a work item to its terminal role lived in
486
+ `lisa-git-submit-pr`, in a section reached *after* that skill delegates the
487
+ entire merge loop to this one. So the skill that observes the merge was never
488
+ told to close anything, and the skill that was told had already handed off. The
489
+ result: **27 of 27** open items carrying the claimed role in this repository had
490
+ a merged pull request — the claimed lane reported 27 things in flight when the
491
+ real number was one.
492
+
493
+ Three properties make the command safe to run unconditionally:
494
+
495
+ 1. **The terminal role is RESOLVED, never assumed.** `lifecycleContract` reads
496
+ `github.labels.build.done` (or the Jira/Linear equivalent), which is
497
+ environment-aware — a repository whose target is `dev` has a different
498
+ terminal role than one merging to production, and a hardcoded label would
499
+ apply the wrong one while looking correct in the repository it was written
500
+ in.
501
+ 2. **It refuses without evidence.** Completion requires a merged pull request in
502
+ the same repository. A command that closes whatever it is pointed at is a way
503
+ to make unfinished work disappear, and the closure is indistinguishable from
504
+ a real one afterwards. Cross-repository references do not count: a downstream
505
+ consumer's PR mentioning an upstream issue is not evidence the upstream issue
506
+ shipped.
507
+ 3. **It is idempotent**, so re-running after a retry converges rather than
508
+ accumulating.
509
+
510
+ It also removes the claimed role rather than only adding the terminal one.
511
+ Leaving both produces exactly the drift this step exists to end — an item that
512
+ is closed *and* still reports as in progress.
513
+
514
+ If the command refuses, do not close by hand. A refusal means the evidence is
515
+ not there, and a lifecycle step performed by hand is one nothing can verify
516
+ happened.
517
+
518
+ **The backstop, for the ones that still slip:** `lisa-work-item.mjs sweep`
519
+ reports every claimed item that already has a merged pull request, and
520
+ `--apply` completes them. Reporting is the default deliberately — a sweep that
521
+ closes things as a side effect of being run is not one anyone runs twice.
522
+
473
523
  ## 4. Terminal states
474
524
 
475
525
  Loop until one of:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -470,6 +470,56 @@ matching Phase 4b's safe default. The full procedure is `lisa-linear-sync`
470
470
  Phase 4b; when the caller's flow already runs a `pr-merged` sync for this
471
471
  merge, confirming that sync ran satisfies this step.
472
472
 
473
+ ### d. Complete the work item
474
+
475
+ Run this once the PR reports `MERGED` and the ancestry check has passed:
476
+
477
+ ```
478
+ node scripts/lisa-work-item.mjs complete --ref <work-item>
479
+ ```
480
+
481
+ resolving the script the usual three ways (installed package, host `scripts/`,
482
+ this repo's own tree).
483
+
484
+ **This step exists because the previous arrangement did not work, measured.**
485
+ The instruction to move a work item to its terminal role lived in
486
+ `lisa-git-submit-pr`, in a section reached *after* that skill delegates the
487
+ entire merge loop to this one. So the skill that observes the merge was never
488
+ told to close anything, and the skill that was told had already handed off. The
489
+ result: **27 of 27** open items carrying the claimed role in this repository had
490
+ a merged pull request — the claimed lane reported 27 things in flight when the
491
+ real number was one.
492
+
493
+ Three properties make the command safe to run unconditionally:
494
+
495
+ 1. **The terminal role is RESOLVED, never assumed.** `lifecycleContract` reads
496
+ `github.labels.build.done` (or the Jira/Linear equivalent), which is
497
+ environment-aware — a repository whose target is `dev` has a different
498
+ terminal role than one merging to production, and a hardcoded label would
499
+ apply the wrong one while looking correct in the repository it was written
500
+ in.
501
+ 2. **It refuses without evidence.** Completion requires a merged pull request in
502
+ the same repository. A command that closes whatever it is pointed at is a way
503
+ to make unfinished work disappear, and the closure is indistinguishable from
504
+ a real one afterwards. Cross-repository references do not count: a downstream
505
+ consumer's PR mentioning an upstream issue is not evidence the upstream issue
506
+ shipped.
507
+ 3. **It is idempotent**, so re-running after a retry converges rather than
508
+ accumulating.
509
+
510
+ It also removes the claimed role rather than only adding the terminal one.
511
+ Leaving both produces exactly the drift this step exists to end — an item that
512
+ is closed *and* still reports as in progress.
513
+
514
+ If the command refuses, do not close by hand. A refusal means the evidence is
515
+ not there, and a lifecycle step performed by hand is one nothing can verify
516
+ happened.
517
+
518
+ **The backstop, for the ones that still slip:** `lisa-work-item.mjs sweep`
519
+ reports every claimed item that already has a merged pull request, and
520
+ `--apply` completes them. Reporting is the default deliberately — a sweep that
521
+ closes things as a side effect of being run is not one anyone runs twice.
522
+
473
523
  ## 4. Terminal states
474
524
 
475
525
  Loop until one of:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -470,6 +470,56 @@ matching Phase 4b's safe default. The full procedure is `lisa-linear-sync`
470
470
  Phase 4b; when the caller's flow already runs a `pr-merged` sync for this
471
471
  merge, confirming that sync ran satisfies this step.
472
472
 
473
+ ### d. Complete the work item
474
+
475
+ Run this once the PR reports `MERGED` and the ancestry check has passed:
476
+
477
+ ```
478
+ node scripts/lisa-work-item.mjs complete --ref <work-item>
479
+ ```
480
+
481
+ resolving the script the usual three ways (installed package, host `scripts/`,
482
+ this repo's own tree).
483
+
484
+ **This step exists because the previous arrangement did not work, measured.**
485
+ The instruction to move a work item to its terminal role lived in
486
+ `lisa-git-submit-pr`, in a section reached *after* that skill delegates the
487
+ entire merge loop to this one. So the skill that observes the merge was never
488
+ told to close anything, and the skill that was told had already handed off. The
489
+ result: **27 of 27** open items carrying the claimed role in this repository had
490
+ a merged pull request — the claimed lane reported 27 things in flight when the
491
+ real number was one.
492
+
493
+ Three properties make the command safe to run unconditionally:
494
+
495
+ 1. **The terminal role is RESOLVED, never assumed.** `lifecycleContract` reads
496
+ `github.labels.build.done` (or the Jira/Linear equivalent), which is
497
+ environment-aware — a repository whose target is `dev` has a different
498
+ terminal role than one merging to production, and a hardcoded label would
499
+ apply the wrong one while looking correct in the repository it was written
500
+ in.
501
+ 2. **It refuses without evidence.** Completion requires a merged pull request in
502
+ the same repository. A command that closes whatever it is pointed at is a way
503
+ to make unfinished work disappear, and the closure is indistinguishable from
504
+ a real one afterwards. Cross-repository references do not count: a downstream
505
+ consumer's PR mentioning an upstream issue is not evidence the upstream issue
506
+ shipped.
507
+ 3. **It is idempotent**, so re-running after a retry converges rather than
508
+ accumulating.
509
+
510
+ It also removes the claimed role rather than only adding the terminal one.
511
+ Leaving both produces exactly the drift this step exists to end — an item that
512
+ is closed *and* still reports as in progress.
513
+
514
+ If the command refuses, do not close by hand. A refusal means the evidence is
515
+ not there, and a lifecycle step performed by hand is one nothing can verify
516
+ happened.
517
+
518
+ **The backstop, for the ones that still slip:** `lisa-work-item.mjs sweep`
519
+ reports every claimed item that already has a merged pull request, and
520
+ `--apply` completes them. Reporting is the default deliberately — a sweep that
521
+ closes things as a side effect of being run is not one anyone runs twice.
522
+
473
523
  ## 4. Terminal states
474
524
 
475
525
  Loop until one of:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -470,6 +470,56 @@ matching Phase 4b's safe default. The full procedure is `lisa-linear-sync`
470
470
  Phase 4b; when the caller's flow already runs a `pr-merged` sync for this
471
471
  merge, confirming that sync ran satisfies this step.
472
472
 
473
+ ### d. Complete the work item
474
+
475
+ Run this once the PR reports `MERGED` and the ancestry check has passed:
476
+
477
+ ```
478
+ node scripts/lisa-work-item.mjs complete --ref <work-item>
479
+ ```
480
+
481
+ resolving the script the usual three ways (installed package, host `scripts/`,
482
+ this repo's own tree).
483
+
484
+ **This step exists because the previous arrangement did not work, measured.**
485
+ The instruction to move a work item to its terminal role lived in
486
+ `lisa-git-submit-pr`, in a section reached *after* that skill delegates the
487
+ entire merge loop to this one. So the skill that observes the merge was never
488
+ told to close anything, and the skill that was told had already handed off. The
489
+ result: **27 of 27** open items carrying the claimed role in this repository had
490
+ a merged pull request — the claimed lane reported 27 things in flight when the
491
+ real number was one.
492
+
493
+ Three properties make the command safe to run unconditionally:
494
+
495
+ 1. **The terminal role is RESOLVED, never assumed.** `lifecycleContract` reads
496
+ `github.labels.build.done` (or the Jira/Linear equivalent), which is
497
+ environment-aware — a repository whose target is `dev` has a different
498
+ terminal role than one merging to production, and a hardcoded label would
499
+ apply the wrong one while looking correct in the repository it was written
500
+ in.
501
+ 2. **It refuses without evidence.** Completion requires a merged pull request in
502
+ the same repository. A command that closes whatever it is pointed at is a way
503
+ to make unfinished work disappear, and the closure is indistinguishable from
504
+ a real one afterwards. Cross-repository references do not count: a downstream
505
+ consumer's PR mentioning an upstream issue is not evidence the upstream issue
506
+ shipped.
507
+ 3. **It is idempotent**, so re-running after a retry converges rather than
508
+ accumulating.
509
+
510
+ It also removes the claimed role rather than only adding the terminal one.
511
+ Leaving both produces exactly the drift this step exists to end — an item that
512
+ is closed *and* still reports as in progress.
513
+
514
+ If the command refuses, do not close by hand. A refusal means the evidence is
515
+ not there, and a lifecycle step performed by hand is one nothing can verify
516
+ happened.
517
+
518
+ **The backstop, for the ones that still slip:** `lisa-work-item.mjs sweep`
519
+ reports every claimed item that already has a merged pull request, and
520
+ `--apply` completes them. Reporting is the default deliberately — a sweep that
521
+ closes things as a side effect of being run is not one anyone runs twice.
522
+
473
523
  ## 4. Terminal states
474
524
 
475
525
  Loop until one of:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "3.42.0",
3
+ "version": "3.43.1",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"