@codyswann/lisa 2.288.0 → 2.289.0

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 (63) hide show
  1. package/cdk/create-only/.github/workflows/deploy.yml +3 -0
  2. package/dist/core/upstream-evidence-manifest.js +3 -3
  3. package/package.json +1 -1
  4. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  5. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  6. package/plugins/lisa/.codex-plugin/skills/lisa-codify-verification/SKILL.md +8 -0
  7. package/plugins/lisa/rules/reference/verification.md +4 -0
  8. package/plugins/lisa/skills/lisa-codify-verification/SKILL.md +8 -0
  9. package/plugins/lisa-agy/plugin.json +1 -1
  10. package/plugins/lisa-agy/skills/lisa-codify-verification/SKILL.md +8 -0
  11. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  12. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  13. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  14. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  15. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  16. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  17. package/plugins/lisa-copilot/rules/reference/verification.md +4 -0
  18. package/plugins/lisa-copilot/skills/lisa-codify-verification/SKILL.md +8 -0
  19. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  20. package/plugins/lisa-cursor/rules/verification-reference.mdc +4 -0
  21. package/plugins/lisa-cursor/skills/lisa-codify-verification/SKILL.md +8 -0
  22. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  24. package/plugins/lisa-expo-agy/plugin.json +1 -1
  25. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  29. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  30. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  34. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  35. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  39. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  40. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  45. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  49. package/plugins/lisa-rails-agy/plugin.json +1 -1
  50. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  54. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  55. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  59. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  60. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  62. package/plugins/src/base/rules/reference/verification.md +4 -0
  63. package/plugins/src/base/skills/lisa-codify-verification/SKILL.md +8 -0
@@ -68,6 +68,9 @@ jobs:
68
68
  # Reference to the quality checks workflow
69
69
  uses: CodySwannGT/lisa/.github/workflows/release.yml@main
70
70
  needs: [determine_environment]
71
+ permissions:
72
+ contents: write
73
+ pull-requests: read
71
74
  with:
72
75
  environment: ${{ needs.determine_environment.outputs.environment }}
73
76
  release_strategy: 'standard-version'
@@ -23,7 +23,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
23
23
  "cdk/copy-overwrite/vitest.cdk.ts": "aea238d214b7eb4c532cebe5bf732dc30b9fd04d938a215bd34a5ec2eff17046",
24
24
  "cdk/copy-overwrite/vitest.config.ts": "ce14179d4ab31011bb012ee1669af7d86b5189bdf2934e0bd9dd666a30e3d01e",
25
25
  "cdk/create-only/.github/workflows/ci.yml": "04cca8fbcb7a5c6da1aeb2b2d00d7a328d15618e4252f1d9dd495052d264d0f5",
26
- "cdk/create-only/.github/workflows/deploy.yml": "5b31ed443511cae5a742238509f1210bb991575deae613aea73c41513c8fe3b8",
26
+ "cdk/create-only/.github/workflows/deploy.yml": "2746e78fb0fbe7b23b30bbcb0f83171e16f6804fd467b3d41d3c69970572af3f",
27
27
  "cdk/create-only/cdk.json": "f89030d8fe145a1dbabd59d89ddee4e16984f222d737f7fcf6b778d911e9fe40",
28
28
  "cdk/create-only/tsconfig.local.json": "d26253827e21fd7c41d30565fe3d339675f119e00bb24c5713a01f57ccd06602",
29
29
  "cdk/create-only/vitest.config.local.ts": "476738b351114a0efbcd3ae4ce1cf016307b55ee41ed8e87c35e28e4639d98f5",
@@ -365,7 +365,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
365
365
  "plugins/src/base/rules/reference/tracked-work.md": "cc956e7a61d8f65bfc4e0e3bc4c3da1b5a9e541683aa17dc1850979d04abac24",
366
366
  "plugins/src/base/rules/reference/upstream-to-lisa.md": "dcf07f8eba66aaf1d132bfaeff73cbf7576279822893235a3c3f8cbc4a4a3323",
367
367
  "plugins/src/base/rules/reference/usage-accounting.md": "d2a24f8f176dbd900beb6e396fc669008b0be0c9033fac5c1c1ecc19002bd7c2",
368
- "plugins/src/base/rules/reference/verification.md": "9aa9ec95a739268181b74d6952fa7cda16c96d633ece6a3e889d3b28a8f8ffb7",
368
+ "plugins/src/base/rules/reference/verification.md": "0a4424d79fae5ce028d08b98523a01f51cbe07c1bcc0a094048d7a25adc075d8",
369
369
  "plugins/src/base/rules/reference/wiki-knowledge-source.md": "305d38e13984c2a64144f302336405d0ccbec493a6ed3ec67d210fed44940717",
370
370
  "plugins/src/base/scripts/automation-run-record.mjs": "89143e06975d8333b137fd2bdb5f12bcd703403752337f00c25d18fefba6a4c8",
371
371
  "plugins/src/base/scripts/automation-status-claude-adapter.mjs": "b1054acf4a5cbbe5354bd62a22b96533bcbc69b6cb9245976ceb8af638a04494",
@@ -394,7 +394,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
394
394
  "plugins/src/base/skills/lisa-automation-status/SKILL.md": "a283afab506d8e52970c6df566b4504a2ed015493cee4de6debe5b62a09782eb",
395
395
  "plugins/src/base/skills/lisa-bug-triage/SKILL.md": "90b0f1388717f81c4e187ab714be01d02a9f41592a4c26487aeb9c26a0959493",
396
396
  "plugins/src/base/skills/lisa-codebase-research/SKILL.md": "77dbc2d7e86e5027df486294de315bb539a2ece84bd4b38e47ccc108f8c2875e",
397
- "plugins/src/base/skills/lisa-codify-verification/SKILL.md": "fc15f1f64766c5e40dbffb160080df519e375a9727ed3e8841df3d1b23fb0ffe",
397
+ "plugins/src/base/skills/lisa-codify-verification/SKILL.md": "45cf7e74697fcc0b8769b31c674dbf0b18e19eb1ceab6a77f608b568512def15",
398
398
  "plugins/src/base/skills/lisa-confluence-prd-intake/SKILL.md": "a6a099abeb32940d44da7e9a6a62c3519f64efa85294c4b996789fa4fba97461",
399
399
  "plugins/src/base/skills/lisa-confluence-to-tracker/SKILL.md": "71ab183ba9f14b83d2e940f4b5ec0e2282b75e30d9d452689d330b5345132bba",
400
400
  "plugins/src/base/skills/lisa-confluence-write-prd/SKILL.md": "548c7f7da38372e3b39bc051d5f09417f5008c880caddb59bc6a8b6e05b0aa7b",
package/package.json CHANGED
@@ -113,7 +113,7 @@
113
113
  "brace-expansion": ">=5.0.6"
114
114
  },
115
115
  "name": "@codyswann/lisa",
116
- "version": "2.288.0",
116
+ "version": "2.289.0",
117
117
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
118
118
  "main": "dist/index.js",
119
119
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -115,6 +115,14 @@ step frames) with deterministic rendering. CI's `verification-coverage` check
115
115
  requires a verification-spec delta on every behavioral change. See the
116
116
  `reference/verification.md` "Making verification concrete (UAT)" section.
117
117
 
118
+ ### 3a. Drift-aware live-environment assertions
119
+
120
+ When the codified test — or the remote re-verification it encodes — runs against a **live, deployed environment**, the environment will not hold still between the original verification and any later run: deploys, out-of-band infra applies, and data churn are normal, not exceptional. Encode the verification accordingly:
121
+
122
+ - **Assert invariants, not snapshot equality.** Pin the properties that define correctness — document shape, exact paths, forbidden values/hosts, internal coherence (e.g. every URL in a discovery document uses the same host) — never a byte-for-byte diff against a captured baseline. A snapshot diff false-fails the moment the environment legitimately moves.
123
+ - **Classify drift, don't just detect it.** When observed state differs from the baseline evidence, treat that as a classification problem, and record the classification in the verdict's canonical `drift` field (`none | progress | regression | unrelated_churn`, defined by the `verdict.json` contract in `reference/verification.md`): **progress** (the change being verified, or a related fix, landed), **regression** (an invariant broke), or **unrelated churn**. Drift classified as progress or unrelated churn passes, with the environment change surfaced as evidence; only a broken invariant fails.
124
+ - **Never encode "the environment will hold still" as an implicit assumption.** Evidence capture that only makes sense if nothing changed between baseline and re-check has that assumption baked in even when no assertion states it — e.g. an OAuth discovery document whose host legitimately flipped from a provider-prefix domain to the canonical vanity host between a local baseline and a remote re-check ~30 minutes later would false-fail a snapshot verifier, while an invariant-asserting verifier passes correctly and records the drift as progress.
125
+
118
126
  ### 4. Run the test in isolation
119
127
 
120
128
  Run only the new test, using whatever per-test invocation the project supports:
@@ -164,6 +164,8 @@ The committed verdict carries the machine-readable half:
164
164
  evidence/<ticket>/verdict.json
165
165
  not_established: [] # what was NOT proved; may be empty
166
166
  not_established_reviewed: true # attests the list was reviewed; may NEVER be omitted
167
+ drift: none # live-environment baseline-vs-now drift classification:
168
+ # none | progress | regression | unrelated_churn
167
169
  artifact: { repository, base_sha, head_sha, build_id, environment, observed_at }
168
170
  evidence: [ { evidence_id, kind, locator,
169
171
  artifact_head_sha, # the head_sha in force when THIS artifact was captured
@@ -205,6 +207,8 @@ Verification happens at two stages in the workflow:
205
207
 
206
208
  Both levels use the same verification types table above. The difference is the environment, not the rigor.
207
209
 
210
+ Remote verification must be **drift-aware**: the target environment may legitimately change between the local baseline and the remote run (its own deploy, out-of-band infra changes, data churn). Assert invariants — shape, exact paths, forbidden values, internal coherence — rather than equality with the local evidence snapshot; when observed state differs from the baseline, classify the drift and record it in the verdict's canonical `drift` field (`none | progress | regression | unrelated_churn`, defined in the `verdict.json` contract above). Only a broken invariant is a failure; never encode "the environment held still" as an implicit assumption.
211
+
208
212
  ---
209
213
 
210
214
  ## Credential-Gated Verification
@@ -115,6 +115,14 @@ step frames) with deterministic rendering. CI's `verification-coverage` check
115
115
  requires a verification-spec delta on every behavioral change. See the
116
116
  `reference/verification.md` "Making verification concrete (UAT)" section.
117
117
 
118
+ ### 3a. Drift-aware live-environment assertions
119
+
120
+ When the codified test — or the remote re-verification it encodes — runs against a **live, deployed environment**, the environment will not hold still between the original verification and any later run: deploys, out-of-band infra applies, and data churn are normal, not exceptional. Encode the verification accordingly:
121
+
122
+ - **Assert invariants, not snapshot equality.** Pin the properties that define correctness — document shape, exact paths, forbidden values/hosts, internal coherence (e.g. every URL in a discovery document uses the same host) — never a byte-for-byte diff against a captured baseline. A snapshot diff false-fails the moment the environment legitimately moves.
123
+ - **Classify drift, don't just detect it.** When observed state differs from the baseline evidence, treat that as a classification problem, and record the classification in the verdict's canonical `drift` field (`none | progress | regression | unrelated_churn`, defined by the `verdict.json` contract in `reference/verification.md`): **progress** (the change being verified, or a related fix, landed), **regression** (an invariant broke), or **unrelated churn**. Drift classified as progress or unrelated churn passes, with the environment change surfaced as evidence; only a broken invariant fails.
124
+ - **Never encode "the environment will hold still" as an implicit assumption.** Evidence capture that only makes sense if nothing changed between baseline and re-check has that assumption baked in even when no assertion states it — e.g. an OAuth discovery document whose host legitimately flipped from a provider-prefix domain to the canonical vanity host between a local baseline and a remote re-check ~30 minutes later would false-fail a snapshot verifier, while an invariant-asserting verifier passes correctly and records the drift as progress.
125
+
118
126
  ### 4. Run the test in isolation
119
127
 
120
128
  Run only the new test, using whatever per-test invocation the project supports:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -115,6 +115,14 @@ step frames) with deterministic rendering. CI's `verification-coverage` check
115
115
  requires a verification-spec delta on every behavioral change. See the
116
116
  `reference/verification.md` "Making verification concrete (UAT)" section.
117
117
 
118
+ ### 3a. Drift-aware live-environment assertions
119
+
120
+ When the codified test — or the remote re-verification it encodes — runs against a **live, deployed environment**, the environment will not hold still between the original verification and any later run: deploys, out-of-band infra applies, and data churn are normal, not exceptional. Encode the verification accordingly:
121
+
122
+ - **Assert invariants, not snapshot equality.** Pin the properties that define correctness — document shape, exact paths, forbidden values/hosts, internal coherence (e.g. every URL in a discovery document uses the same host) — never a byte-for-byte diff against a captured baseline. A snapshot diff false-fails the moment the environment legitimately moves.
123
+ - **Classify drift, don't just detect it.** When observed state differs from the baseline evidence, treat that as a classification problem, and record the classification in the verdict's canonical `drift` field (`none | progress | regression | unrelated_churn`, defined by the `verdict.json` contract in `reference/verification.md`): **progress** (the change being verified, or a related fix, landed), **regression** (an invariant broke), or **unrelated churn**. Drift classified as progress or unrelated churn passes, with the environment change surfaced as evidence; only a broken invariant fails.
124
+ - **Never encode "the environment will hold still" as an implicit assumption.** Evidence capture that only makes sense if nothing changed between baseline and re-check has that assumption baked in even when no assertion states it — e.g. an OAuth discovery document whose host legitimately flipped from a provider-prefix domain to the canonical vanity host between a local baseline and a remote re-check ~30 minutes later would false-fail a snapshot verifier, while an invariant-asserting verifier passes correctly and records the drift as progress.
125
+
118
126
  ### 4. Run the test in isolation
119
127
 
120
128
  Run only the new test, using whatever per-test invocation the project supports:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -164,6 +164,8 @@ The committed verdict carries the machine-readable half:
164
164
  evidence/<ticket>/verdict.json
165
165
  not_established: [] # what was NOT proved; may be empty
166
166
  not_established_reviewed: true # attests the list was reviewed; may NEVER be omitted
167
+ drift: none # live-environment baseline-vs-now drift classification:
168
+ # none | progress | regression | unrelated_churn
167
169
  artifact: { repository, base_sha, head_sha, build_id, environment, observed_at }
168
170
  evidence: [ { evidence_id, kind, locator,
169
171
  artifact_head_sha, # the head_sha in force when THIS artifact was captured
@@ -205,6 +207,8 @@ Verification happens at two stages in the workflow:
205
207
 
206
208
  Both levels use the same verification types table above. The difference is the environment, not the rigor.
207
209
 
210
+ Remote verification must be **drift-aware**: the target environment may legitimately change between the local baseline and the remote run (its own deploy, out-of-band infra changes, data churn). Assert invariants — shape, exact paths, forbidden values, internal coherence — rather than equality with the local evidence snapshot; when observed state differs from the baseline, classify the drift and record it in the verdict's canonical `drift` field (`none | progress | regression | unrelated_churn`, defined in the `verdict.json` contract above). Only a broken invariant is a failure; never encode "the environment held still" as an implicit assumption.
211
+
208
212
  ---
209
213
 
210
214
  ## Credential-Gated Verification
@@ -115,6 +115,14 @@ step frames) with deterministic rendering. CI's `verification-coverage` check
115
115
  requires a verification-spec delta on every behavioral change. See the
116
116
  `reference/verification.md` "Making verification concrete (UAT)" section.
117
117
 
118
+ ### 3a. Drift-aware live-environment assertions
119
+
120
+ When the codified test — or the remote re-verification it encodes — runs against a **live, deployed environment**, the environment will not hold still between the original verification and any later run: deploys, out-of-band infra applies, and data churn are normal, not exceptional. Encode the verification accordingly:
121
+
122
+ - **Assert invariants, not snapshot equality.** Pin the properties that define correctness — document shape, exact paths, forbidden values/hosts, internal coherence (e.g. every URL in a discovery document uses the same host) — never a byte-for-byte diff against a captured baseline. A snapshot diff false-fails the moment the environment legitimately moves.
123
+ - **Classify drift, don't just detect it.** When observed state differs from the baseline evidence, treat that as a classification problem, and record the classification in the verdict's canonical `drift` field (`none | progress | regression | unrelated_churn`, defined by the `verdict.json` contract in `reference/verification.md`): **progress** (the change being verified, or a related fix, landed), **regression** (an invariant broke), or **unrelated churn**. Drift classified as progress or unrelated churn passes, with the environment change surfaced as evidence; only a broken invariant fails.
124
+ - **Never encode "the environment will hold still" as an implicit assumption.** Evidence capture that only makes sense if nothing changed between baseline and re-check has that assumption baked in even when no assertion states it — e.g. an OAuth discovery document whose host legitimately flipped from a provider-prefix domain to the canonical vanity host between a local baseline and a remote re-check ~30 minutes later would false-fail a snapshot verifier, while an invariant-asserting verifier passes correctly and records the drift as progress.
125
+
118
126
  ### 4. Run the test in isolation
119
127
 
120
128
  Run only the new test, using whatever per-test invocation the project supports:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -169,6 +169,8 @@ The committed verdict carries the machine-readable half:
169
169
  evidence/<ticket>/verdict.json
170
170
  not_established: [] # what was NOT proved; may be empty
171
171
  not_established_reviewed: true # attests the list was reviewed; may NEVER be omitted
172
+ drift: none # live-environment baseline-vs-now drift classification:
173
+ # none | progress | regression | unrelated_churn
172
174
  artifact: { repository, base_sha, head_sha, build_id, environment, observed_at }
173
175
  evidence: [ { evidence_id, kind, locator,
174
176
  artifact_head_sha, # the head_sha in force when THIS artifact was captured
@@ -210,6 +212,8 @@ Verification happens at two stages in the workflow:
210
212
 
211
213
  Both levels use the same verification types table above. The difference is the environment, not the rigor.
212
214
 
215
+ Remote verification must be **drift-aware**: the target environment may legitimately change between the local baseline and the remote run (its own deploy, out-of-band infra changes, data churn). Assert invariants — shape, exact paths, forbidden values, internal coherence — rather than equality with the local evidence snapshot; when observed state differs from the baseline, classify the drift and record it in the verdict's canonical `drift` field (`none | progress | regression | unrelated_churn`, defined in the `verdict.json` contract above). Only a broken invariant is a failure; never encode "the environment held still" as an implicit assumption.
216
+
213
217
  ---
214
218
 
215
219
  ## Credential-Gated Verification
@@ -115,6 +115,14 @@ step frames) with deterministic rendering. CI's `verification-coverage` check
115
115
  requires a verification-spec delta on every behavioral change. See the
116
116
  `reference/verification.md` "Making verification concrete (UAT)" section.
117
117
 
118
+ ### 3a. Drift-aware live-environment assertions
119
+
120
+ When the codified test — or the remote re-verification it encodes — runs against a **live, deployed environment**, the environment will not hold still between the original verification and any later run: deploys, out-of-band infra applies, and data churn are normal, not exceptional. Encode the verification accordingly:
121
+
122
+ - **Assert invariants, not snapshot equality.** Pin the properties that define correctness — document shape, exact paths, forbidden values/hosts, internal coherence (e.g. every URL in a discovery document uses the same host) — never a byte-for-byte diff against a captured baseline. A snapshot diff false-fails the moment the environment legitimately moves.
123
+ - **Classify drift, don't just detect it.** When observed state differs from the baseline evidence, treat that as a classification problem, and record the classification in the verdict's canonical `drift` field (`none | progress | regression | unrelated_churn`, defined by the `verdict.json` contract in `reference/verification.md`): **progress** (the change being verified, or a related fix, landed), **regression** (an invariant broke), or **unrelated churn**. Drift classified as progress or unrelated churn passes, with the environment change surfaced as evidence; only a broken invariant fails.
124
+ - **Never encode "the environment will hold still" as an implicit assumption.** Evidence capture that only makes sense if nothing changed between baseline and re-check has that assumption baked in even when no assertion states it — e.g. an OAuth discovery document whose host legitimately flipped from a provider-prefix domain to the canonical vanity host between a local baseline and a remote re-check ~30 minutes later would false-fail a snapshot verifier, while an invariant-asserting verifier passes correctly and records the drift as progress.
125
+
118
126
  ### 4. Run the test in isolation
119
127
 
120
128
  Run only the new test, using whatever per-test invocation the project supports:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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": "2.288.0",
3
+ "version": "2.289.0",
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-rails",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.288.0",
3
+ "version": "2.289.0",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -164,6 +164,8 @@ The committed verdict carries the machine-readable half:
164
164
  evidence/<ticket>/verdict.json
165
165
  not_established: [] # what was NOT proved; may be empty
166
166
  not_established_reviewed: true # attests the list was reviewed; may NEVER be omitted
167
+ drift: none # live-environment baseline-vs-now drift classification:
168
+ # none | progress | regression | unrelated_churn
167
169
  artifact: { repository, base_sha, head_sha, build_id, environment, observed_at }
168
170
  evidence: [ { evidence_id, kind, locator,
169
171
  artifact_head_sha, # the head_sha in force when THIS artifact was captured
@@ -205,6 +207,8 @@ Verification happens at two stages in the workflow:
205
207
 
206
208
  Both levels use the same verification types table above. The difference is the environment, not the rigor.
207
209
 
210
+ Remote verification must be **drift-aware**: the target environment may legitimately change between the local baseline and the remote run (its own deploy, out-of-band infra changes, data churn). Assert invariants — shape, exact paths, forbidden values, internal coherence — rather than equality with the local evidence snapshot; when observed state differs from the baseline, classify the drift and record it in the verdict's canonical `drift` field (`none | progress | regression | unrelated_churn`, defined in the `verdict.json` contract above). Only a broken invariant is a failure; never encode "the environment held still" as an implicit assumption.
211
+
208
212
  ---
209
213
 
210
214
  ## Credential-Gated Verification
@@ -115,6 +115,14 @@ step frames) with deterministic rendering. CI's `verification-coverage` check
115
115
  requires a verification-spec delta on every behavioral change. See the
116
116
  `reference/verification.md` "Making verification concrete (UAT)" section.
117
117
 
118
+ ### 3a. Drift-aware live-environment assertions
119
+
120
+ When the codified test — or the remote re-verification it encodes — runs against a **live, deployed environment**, the environment will not hold still between the original verification and any later run: deploys, out-of-band infra applies, and data churn are normal, not exceptional. Encode the verification accordingly:
121
+
122
+ - **Assert invariants, not snapshot equality.** Pin the properties that define correctness — document shape, exact paths, forbidden values/hosts, internal coherence (e.g. every URL in a discovery document uses the same host) — never a byte-for-byte diff against a captured baseline. A snapshot diff false-fails the moment the environment legitimately moves.
123
+ - **Classify drift, don't just detect it.** When observed state differs from the baseline evidence, treat that as a classification problem, and record the classification in the verdict's canonical `drift` field (`none | progress | regression | unrelated_churn`, defined by the `verdict.json` contract in `reference/verification.md`): **progress** (the change being verified, or a related fix, landed), **regression** (an invariant broke), or **unrelated churn**. Drift classified as progress or unrelated churn passes, with the environment change surfaced as evidence; only a broken invariant fails.
124
+ - **Never encode "the environment will hold still" as an implicit assumption.** Evidence capture that only makes sense if nothing changed between baseline and re-check has that assumption baked in even when no assertion states it — e.g. an OAuth discovery document whose host legitimately flipped from a provider-prefix domain to the canonical vanity host between a local baseline and a remote re-check ~30 minutes later would false-fail a snapshot verifier, while an invariant-asserting verifier passes correctly and records the drift as progress.
125
+
118
126
  ### 4. Run the test in isolation
119
127
 
120
128
  Run only the new test, using whatever per-test invocation the project supports: