@codyswann/lisa 2.342.6 → 2.343.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 (140) hide show
  1. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  2. package/dist/core/upstream-evidence-manifest.js +27 -16
  3. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  4. package/package.json +1 -1
  5. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  6. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  7. package/plugins/lisa/.codex-plugin/skills/lisa-acceptance-criteria/SKILL.md +1 -0
  8. package/plugins/lisa/.codex-plugin/skills/lisa-codify-verification/SKILL.md +16 -12
  9. package/plugins/lisa/.codex-plugin/skills/lisa-implement/SKILL.md +2 -2
  10. package/plugins/lisa/.codex-plugin/skills/lisa-research/SKILL.md +9 -1
  11. package/plugins/lisa/.codex-plugin/skills/lisa-spec-conformance/SKILL.md +15 -1
  12. package/plugins/lisa/.codex-plugin/skills/lisa-task-decomposition/SKILL.md +2 -0
  13. package/plugins/lisa/.codex-plugin/skills/lisa-tdd-implementation/SKILL.md +1 -0
  14. package/plugins/lisa/.codex-plugin/skills/lisa-test-strategy/SKILL.md +4 -2
  15. package/plugins/lisa/.codex-plugin/skills/lisa-verification-lifecycle/SKILL.md +3 -2
  16. package/plugins/lisa/.codex-plugin/skills/lisa-verify/SKILL.md +1 -1
  17. package/plugins/lisa/hooks/threshold-ratchet-compare.mjs +23 -0
  18. package/plugins/lisa/rules/eager/bdd-e2e-coverage.md +49 -0
  19. package/plugins/lisa/rules/eager/verification.md +3 -2
  20. package/plugins/lisa/rules/reference/bdd-e2e-coverage.md +182 -0
  21. package/plugins/lisa/rules/reference/intent-routing.md +7 -6
  22. package/plugins/lisa/rules/reference/verification.md +7 -6
  23. package/plugins/lisa/skills/lisa-acceptance-criteria/SKILL.md +1 -0
  24. package/plugins/lisa/skills/lisa-codify-verification/SKILL.md +16 -12
  25. package/plugins/lisa/skills/lisa-implement/SKILL.md +2 -2
  26. package/plugins/lisa/skills/lisa-research/SKILL.md +9 -1
  27. package/plugins/lisa/skills/lisa-spec-conformance/SKILL.md +15 -1
  28. package/plugins/lisa/skills/lisa-task-decomposition/SKILL.md +2 -0
  29. package/plugins/lisa/skills/lisa-tdd-implementation/SKILL.md +1 -0
  30. package/plugins/lisa/skills/lisa-test-strategy/SKILL.md +4 -2
  31. package/plugins/lisa/skills/lisa-verification-lifecycle/SKILL.md +3 -2
  32. package/plugins/lisa/skills/lisa-verify/SKILL.md +1 -1
  33. package/plugins/lisa-agy/plugin.json +1 -1
  34. package/plugins/lisa-agy/skills/lisa-acceptance-criteria/SKILL.md +1 -0
  35. package/plugins/lisa-agy/skills/lisa-codify-verification/SKILL.md +16 -12
  36. package/plugins/lisa-agy/skills/lisa-implement/SKILL.md +2 -2
  37. package/plugins/lisa-agy/skills/lisa-research/SKILL.md +9 -1
  38. package/plugins/lisa-agy/skills/lisa-spec-conformance/SKILL.md +15 -1
  39. package/plugins/lisa-agy/skills/lisa-task-decomposition/SKILL.md +2 -0
  40. package/plugins/lisa-agy/skills/lisa-tdd-implementation/SKILL.md +1 -0
  41. package/plugins/lisa-agy/skills/lisa-test-strategy/SKILL.md +4 -2
  42. package/plugins/lisa-agy/skills/lisa-verification-lifecycle/SKILL.md +3 -2
  43. package/plugins/lisa-agy/skills/lisa-verify/SKILL.md +1 -1
  44. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  46. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  47. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-copilot/hooks/threshold-ratchet-compare.mjs +23 -0
  51. package/plugins/lisa-copilot/rules/eager/bdd-e2e-coverage.md +49 -0
  52. package/plugins/lisa-copilot/rules/eager/verification.md +3 -2
  53. package/plugins/lisa-copilot/rules/reference/bdd-e2e-coverage.md +182 -0
  54. package/plugins/lisa-copilot/rules/reference/intent-routing.md +7 -6
  55. package/plugins/lisa-copilot/rules/reference/verification.md +7 -6
  56. package/plugins/lisa-copilot/skills/lisa-acceptance-criteria/SKILL.md +1 -0
  57. package/plugins/lisa-copilot/skills/lisa-codify-verification/SKILL.md +16 -12
  58. package/plugins/lisa-copilot/skills/lisa-implement/SKILL.md +2 -2
  59. package/plugins/lisa-copilot/skills/lisa-research/SKILL.md +9 -1
  60. package/plugins/lisa-copilot/skills/lisa-spec-conformance/SKILL.md +15 -1
  61. package/plugins/lisa-copilot/skills/lisa-task-decomposition/SKILL.md +2 -0
  62. package/plugins/lisa-copilot/skills/lisa-tdd-implementation/SKILL.md +1 -0
  63. package/plugins/lisa-copilot/skills/lisa-test-strategy/SKILL.md +4 -2
  64. package/plugins/lisa-copilot/skills/lisa-verification-lifecycle/SKILL.md +3 -2
  65. package/plugins/lisa-copilot/skills/lisa-verify/SKILL.md +1 -1
  66. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-cursor/hooks/threshold-ratchet-compare.mjs +23 -0
  68. package/plugins/lisa-cursor/rules/bdd-e2e-coverage-reference.mdc +187 -0
  69. package/plugins/lisa-cursor/rules/bdd-e2e-coverage.mdc +54 -0
  70. package/plugins/lisa-cursor/rules/intent-routing-reference.mdc +7 -6
  71. package/plugins/lisa-cursor/rules/verification-reference.mdc +7 -6
  72. package/plugins/lisa-cursor/rules/verification.mdc +3 -2
  73. package/plugins/lisa-cursor/skills/lisa-acceptance-criteria/SKILL.md +1 -0
  74. package/plugins/lisa-cursor/skills/lisa-codify-verification/SKILL.md +16 -12
  75. package/plugins/lisa-cursor/skills/lisa-implement/SKILL.md +2 -2
  76. package/plugins/lisa-cursor/skills/lisa-research/SKILL.md +9 -1
  77. package/plugins/lisa-cursor/skills/lisa-spec-conformance/SKILL.md +15 -1
  78. package/plugins/lisa-cursor/skills/lisa-task-decomposition/SKILL.md +2 -0
  79. package/plugins/lisa-cursor/skills/lisa-tdd-implementation/SKILL.md +1 -0
  80. package/plugins/lisa-cursor/skills/lisa-test-strategy/SKILL.md +4 -2
  81. package/plugins/lisa-cursor/skills/lisa-verification-lifecycle/SKILL.md +3 -2
  82. package/plugins/lisa-cursor/skills/lisa-verify/SKILL.md +1 -1
  83. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  85. package/plugins/lisa-expo-agy/plugin.json +1 -1
  86. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  89. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  90. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  91. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  93. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  94. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  95. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  96. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  97. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  98. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  99. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  100. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  101. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  102. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  103. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  104. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  105. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  106. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  107. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  108. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  109. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  110. package/plugins/lisa-rails-agy/plugin.json +1 -1
  111. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  112. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  113. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  114. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  115. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  116. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  117. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  118. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  119. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  120. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  121. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  122. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  123. package/plugins/src/base/hooks/threshold-ratchet-compare.mjs +23 -0
  124. package/plugins/src/base/rules/eager/bdd-e2e-coverage.md +49 -0
  125. package/plugins/src/base/rules/eager/verification.md +3 -2
  126. package/plugins/src/base/rules/reference/bdd-e2e-coverage.md +182 -0
  127. package/plugins/src/base/rules/reference/intent-routing.md +7 -6
  128. package/plugins/src/base/rules/reference/verification.md +7 -6
  129. package/plugins/src/base/skills/lisa-acceptance-criteria/SKILL.md +1 -0
  130. package/plugins/src/base/skills/lisa-codify-verification/SKILL.md +16 -12
  131. package/plugins/src/base/skills/lisa-implement/SKILL.md +2 -2
  132. package/plugins/src/base/skills/lisa-research/SKILL.md +9 -1
  133. package/plugins/src/base/skills/lisa-spec-conformance/SKILL.md +15 -1
  134. package/plugins/src/base/skills/lisa-task-decomposition/SKILL.md +2 -0
  135. package/plugins/src/base/skills/lisa-tdd-implementation/SKILL.md +1 -0
  136. package/plugins/src/base/skills/lisa-test-strategy/SKILL.md +4 -2
  137. package/plugins/src/base/skills/lisa-verification-lifecycle/SKILL.md +3 -2
  138. package/plugins/src/base/skills/lisa-verify/SKILL.md +1 -1
  139. package/rails/copy-overwrite/scripts/threshold-ratchet-compare.mjs +23 -0
  140. package/typescript/copy-overwrite/scripts/threshold-ratchet-compare.mjs +23 -0
@@ -64,6 +64,7 @@ TDD Cycle:
64
64
  - If the imported module doesn't exist, Jest reports 0 tests found (not N failed) — this is expected RED behavior
65
65
  - For a Fix task, or a Build task that changes user-visible behavior, include a regression test at the highest practical observation level for the reported surface. If the project has a browser, device, or end-to-end harness for that platform (for example Playwright, Maestro, Detox, Cypress, or an equivalent runtime), the RED test plan must include a deterministic spec against the reported surface, using mocked or seeded data where needed.
66
66
  - The team lead may not waive, defer, or mark that user-visible regression spec as optional, "if cheap", or equivalent. The only exits are a recorded absence of an end-to-end harness for the affected platform, or a genuine technical blocker with a linked build-ready follow-up ticket created before merge and referenced from the PR and source work item.
67
+ - For frontend work, the `bdd-e2e-coverage` rule governs what that spec is sealing: before writing it, add or update the Gherkin scenario with its stable ID in the project's behavior contract, then write aligned automation in the project's configured runner for each platform the scenario requires. The scenario is the specification the RED test encodes — write the scenario first, in the same PR.
67
68
  - A regression spec is not complete merely because it exists. Completion evidence must prove the spec actually ran and passed in PR CI with a named log line, reporter output, or equivalent execution record. Guard against `test.skip`, suite-level environment gates, shard filters, and "0 tests" passes.
68
69
 
69
70
  ### GREEN Phase
@@ -12,8 +12,9 @@ Design test strategies, write tests, and review test quality.
12
12
  1. **Read existing tests** -- understand the project's test conventions (describe/it structure, naming, helpers)
13
13
  2. **Identify test types needed** -- unit, integration, E2E based on the scope of changes
14
14
  3. **Map edge cases** -- boundary values, empty inputs, error states, concurrency scenarios
15
- 4. **Check coverage gaps** -- run existing tests to understand current coverage of affected files
16
- 5. **Design verification commands** -- proof commands that empirically demonstrate the code works
15
+ 4. **For frontend scope, start from the behavior contract** -- read the project's Gherkin scenarios and coverage map, identify which scenario IDs this work adds or changes, and treat each required scenario-platform obligation as a strategy line item per the `bdd-e2e-coverage` rule
16
+ 5. **Check coverage gaps** -- run existing tests to understand current coverage of affected files
17
+ 6. **Design verification commands** -- proof commands that empirically demonstrate the code works
17
18
 
18
19
  ## Test Writing Process
19
20
 
@@ -56,6 +57,7 @@ Structure findings as:
56
57
 
57
58
  - Always run `bun run test` to understand current test state before recommending or writing new tests
58
59
  - Match existing test conventions -- do not introduce new test patterns
60
+ - For frontend work, the strategy is not complete until every required scenario-platform obligation has aligned e2e automation in the project's configured runner for that platform, or a dated waiver naming the runner limitation (`bdd-e2e-coverage`). A unit test, a route boot, or a passing test on a different platform never seals an obligation
59
61
  - Every test must have a clear "why" -- no tests for testing's sake
60
62
  - Focus on testing behavior, not implementation details
61
63
  - Verification commands must be runnable locally (no CI/CD dependencies)
@@ -91,7 +91,7 @@ If auto-merge is enabled while the regression spec is still in flight, disable a
91
91
 
92
92
  After each empirical verification produces PASS evidence, invoke the `codify-verification` skill to encode the verification as an automated regression test. The manual proof becomes a repeatable check that catches future regressions.
93
93
 
94
- The `codify-verification` skill maps the verification type to the appropriate framework (Playwright for browser/UI, integration test for API/DB/auth, benchmark for performance, etc.), generates a deterministic test that asserts the same observable outcome the verification just confirmed, runs it in isolation to confirm PASS, and commits it in the same PR as the change. For **frontend work**, codification is dual-runner: a Playwright spec in the project's Playwright test runner AND a Maestro flow in the Maestro test runner whenever the project supports Maestro (`.maestro/` directory, `maestro:test` script, or Maestro CI workflow) both encoding the same verified journey, neither a substitute for the other.
94
+ The `codify-verification` skill maps the verification type to the appropriate framework (Playwright for browser/UI, integration test for API/DB/auth, benchmark for performance, etc.), generates a deterministic test that asserts the same observable outcome the verification just confirmed, runs it in isolation to confirm PASS, and commits it in the same PR as the change. For **frontend work**, codification is multi-runner and governed by the `bdd-e2e-coverage` rule: the behavior exists as a Gherkin scenario with a stable ID in the project's behavior contract, and the same verified journey is encoded in the project's configured runner for every platform that scenario requires neither a substitute for the other, since they guard different platforms.
95
95
 
96
96
  Codification is mandatory for every empirical verification type with one exception set: PR, Documentation, Deploy, and Investigate-Only spikes — those have inherently non-behavioral proof. For every other type, skipping codification is not allowed; if codification is genuinely impossible (e.g., the test framework does not exist and cannot be installed in scope), escalate via the Escalation Protocol rather than silently skipping.
97
97
 
@@ -251,7 +251,7 @@ Agents must follow this sequence unless explicitly instructed otherwise:
251
251
  8. Implement the change.
252
252
  9. Execute verification plan — run the actual system and observe results.
253
253
  10. Collect proof artifacts.
254
- 11. Codify — for each passing empirical verification, invoke `codify-verification` to encode it as a regression test (Playwright for UI, integration test for API/DB/auth, benchmark for performance, etc.) and commit the test in the same PR. Frontend work codifies into every supported UI runner: Playwright spec + Maestro flow when the project supports Maestro (see the dual-runner section of `codify-verification`).
254
+ 11. Codify — for each passing empirical verification, invoke `codify-verification` to encode it as a regression test (Playwright for UI, integration test for API/DB/auth, benchmark for performance, etc.) and commit the test in the same PR. Frontend work also updates the behavior contract and codifies into the project's configured runner for every platform the scenario requires, then regenerates the coverage matrix (`bdd-e2e-coverage`; see the frontend multi-runner section of `codify-verification`).
255
255
  12. Run spec conformance — build coverage matrix against the spec source (plan/ticket/issue), flag scope creep and untraceable changes, produce verdict.
256
256
  13. Summarize what changed, what was verified, what was codified, conformance verdict, and remaining risk.
257
257
  14. Label the result with a verification level.
@@ -373,6 +373,7 @@ A task is done only when:
373
373
  - Required verification surfaces and tooling surfaces are used or explicitly unavailable
374
374
  - Proof artifacts are captured
375
375
  - Every passing empirical verification is codified as a regression test (or has an explicit, documented skip reason from the allowed set)
376
+ - For frontend work, the `bdd-e2e-coverage` contract is satisfied: every user-facing behavior added or changed exists as a Gherkin scenario with a stable ID traceable to the work item, every required scenario-platform obligation is mapped to aligned e2e automation in the project's configured runner for that platform or carries a dated waiver, and the coverage gate passes with the matrix and burndown regenerated and committed. Missing BDD coverage is a verification failure, not a warning
376
377
  - For a leaf work unit, every typed `[EVIDENCE: <artifact-type>: <name>]` marker declared in its Validation Journey has a captured, non-empty artifact of the declared type attached to the ticket (the evidence manifest is fully satisfied)
377
378
  - Cross-work-item `EVIDENCE-REF` pointers were excluded from the local manifest and did not satisfy S14 or completion; a runtime-changing leaf has at least one local claiming marker
378
379
  - Spec conformance verdict is `CONFORMS` (not `PARTIAL`, not `DIVERGES`)
@@ -35,7 +35,7 @@ Treat the first successful lead-spawn request (or, on the Codex fallback, the fi
35
35
 
36
36
  Execute the **Verify** flow as defined in the `intent-routing` rule (loaded via the lisa plugin). The flow includes:
37
37
 
38
- 1. **Pre-flight: codification gate** — confirm that every passing local empirical verification on this branch was codified as a regression test (the Implement flow's codify step). If any verification has no committed test and no allowed skip reason (PR / Documentation / Deploy / Investigate-Only), invoke `codify-verification` now and amend the PR before shipping. For frontend work the gate is dual-runner: a Playwright spec AND, when the project supports Maestro (`.maestro/`, `maestro:test` script, or Maestro CI workflow), a Maestro flow for the same journey a missing runner needs a recorded absence or a linked build-ready follow-up ticket, never a silent skip. A change cannot ship until its verifications are guarded.
38
+ 1. **Pre-flight: codification gate** — confirm that every passing local empirical verification on this branch was codified as a regression test (the Implement flow's codify step). If any verification has no committed test and no allowed skip reason (PR / Documentation / Deploy / Investigate-Only), invoke `codify-verification` now and amend the PR before shipping. For frontend work the gate additionally enforces the `bdd-e2e-coverage` rule: the shipped behavior exists as a Gherkin scenario with a stable ID, every required scenario-platform obligation has aligned automation in the project's configured runner for that platform or a dated waiver, and the project's coverage gate passes with the matrix regenerated. A missing runner is never a bare recorded absence it needs a dated `platformWaivers` entry (per the rule) and, where the runner could reasonably be added, a linked build-ready follow-up ticket referenced from it; never a silent skip. Missing BDD coverage is a verification failure that blocks the ship, not a warning. A change cannot ship until its verifications are guarded.
39
39
  2. **Commit** any pending changes via `lisa-git-commit`
40
40
  3. **Push and PR** via `lisa-git-submit-pr`
41
41
  4. **PR Watch Loop** — drive the PR to MERGED via `lisa-drive-pr-to-merge`, the single source of truth for clearing every blocker: auto-merge with direct-merge fallback, `BEHIND` re-sync, conflict resolution, failing-check fixes, human + bot review-comment handling with thread resolution (it invokes `lisa-pull-request-review` itself), stale `CHANGES_REQUESTED` dismissal, and post-merge ancestry verification. Do not re-implement the loop or its terminal conditions.
@@ -72,6 +72,29 @@ export function compareConstraints(relPath, base, current) {
72
72
  });
73
73
  continue;
74
74
  }
75
+ // A bound's DIRECTION carries as much of the gate as its number. Flipping
76
+ // `rate>=0.99` to `rate<=0.99` keeps the key and the value and inverts the
77
+ // meaning: "at least 99% success" becomes "at most 99% success", a gate
78
+ // that now passes when the system is broken. Comparing only values, that
79
+ // read as unchanged.
80
+ //
81
+ // Rejected rather than re-evaluated in the new direction, because the two
82
+ // bounds are not commensurable — there is no value at which `<=0.99` is
83
+ // "no weaker than" `>=0.99`. The honest verdict is that the change cannot
84
+ // be proven safe, so it belongs in the existing allow-list path where a
85
+ // human records why, not in a comparison that would have to invent an
86
+ // ordering between incomparable gates.
87
+ if (currentC.direction !== baseC.direction) {
88
+ findings.push({
89
+ file: relPath,
90
+ key,
91
+ type: TYPE_WEAKENED,
92
+ base: baseC.value,
93
+ current: currentC.value,
94
+ message: `${relPath}: ${key} changed bound direction (${baseC.direction} → ${currentC.direction}) — the gate's meaning is inverted, so preserving it cannot be proven from the value alone.`,
95
+ });
96
+ continue;
97
+ }
75
98
  const weakened =
76
99
  baseC.direction === "min"
77
100
  ? currentC.value < baseC.value
@@ -72,6 +72,29 @@ export function compareConstraints(relPath, base, current) {
72
72
  });
73
73
  continue;
74
74
  }
75
+ // A bound's DIRECTION carries as much of the gate as its number. Flipping
76
+ // `rate>=0.99` to `rate<=0.99` keeps the key and the value and inverts the
77
+ // meaning: "at least 99% success" becomes "at most 99% success", a gate
78
+ // that now passes when the system is broken. Comparing only values, that
79
+ // read as unchanged.
80
+ //
81
+ // Rejected rather than re-evaluated in the new direction, because the two
82
+ // bounds are not commensurable — there is no value at which `<=0.99` is
83
+ // "no weaker than" `>=0.99`. The honest verdict is that the change cannot
84
+ // be proven safe, so it belongs in the existing allow-list path where a
85
+ // human records why, not in a comparison that would have to invent an
86
+ // ordering between incomparable gates.
87
+ if (currentC.direction !== baseC.direction) {
88
+ findings.push({
89
+ file: relPath,
90
+ key,
91
+ type: TYPE_WEAKENED,
92
+ base: baseC.value,
93
+ current: currentC.value,
94
+ message: `${relPath}: ${key} changed bound direction (${baseC.direction} → ${currentC.direction}) — the gate's meaning is inverted, so preserving it cannot be proven from the value alone.`,
95
+ });
96
+ continue;
97
+ }
75
98
  const weakened =
76
99
  baseC.direction === "min"
77
100
  ? currentC.value < baseC.value