@codyswann/lisa 4.69.4 → 4.70.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 (99) hide show
  1. package/all/copy-overwrite/scripts/lib/history-secret-git.mjs +212 -0
  2. package/all/copy-overwrite/scripts/lib/history-secret-policy.mjs +39 -0
  3. package/all/copy-overwrite/scripts/lib/history-secret-scanner.mjs +353 -0
  4. package/all/copy-overwrite/scripts/lisa-gates.mjs +26 -10
  5. package/all/copy-overwrite/scripts/lisa-history-secrets.mjs +122 -0
  6. package/all/copy-overwrite/scripts/lisa-rails-prepush.mjs +90 -0
  7. package/cdk/create-only/stryker.conf.json +2 -0
  8. package/cdk/package-lisa/package.lisa.json +10 -6
  9. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  10. package/dist/core/lisa-owned-hash-ledger.js +46 -0
  11. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  12. package/dist/core/lisa.d.ts +17 -3
  13. package/dist/core/lisa.d.ts.map +1 -1
  14. package/dist/core/lisa.js +74 -21
  15. package/dist/core/lisa.js.map +1 -1
  16. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  17. package/dist/core/plugin-command.d.ts +21 -0
  18. package/dist/core/plugin-command.d.ts.map +1 -0
  19. package/dist/core/plugin-command.js +121 -0
  20. package/dist/core/plugin-command.js.map +1 -0
  21. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  22. package/dist/core/upstream-evidence-manifest.js +54 -18
  23. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  24. package/dist/migrations/ensure-required-history-secret-gate.d.ts +19 -0
  25. package/dist/migrations/ensure-required-history-secret-gate.d.ts.map +1 -0
  26. package/dist/migrations/ensure-required-history-secret-gate.js +94 -0
  27. package/dist/migrations/ensure-required-history-secret-gate.js.map +1 -0
  28. package/dist/migrations/index.d.ts +1 -0
  29. package/dist/migrations/index.d.ts.map +1 -1
  30. package/dist/migrations/index.js +3 -0
  31. package/dist/migrations/index.js.map +1 -1
  32. package/eslint-plugin-component-structure/package.json +3 -0
  33. package/expo/create-only/stryker.conf.json +2 -0
  34. package/expo/package-lisa/package.lisa.json +3 -3
  35. package/harper-fabric/package-lisa/package.lisa.json +7 -7
  36. package/nestjs/package-lisa/package.lisa.json +2 -2
  37. package/package.json +28 -19
  38. package/phaser/package-lisa/package.lisa.json +7 -7
  39. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  41. package/plugins/lisa-agy/plugin.json +1 -1
  42. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  45. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  51. package/plugins/lisa-expo-agy/plugin.json +1 -1
  52. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  56. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  57. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  61. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  62. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  66. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  67. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  71. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  72. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  73. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  76. package/plugins/lisa-rails-agy/plugin.json +1 -1
  77. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  78. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  79. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  80. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  81. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  82. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  83. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  85. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  86. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  87. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  88. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  89. package/rails/copy-overwrite/.rubocop.yml +0 -2
  90. package/rails/copy-overwrite/Gemfile.lisa +8 -8
  91. package/rails/copy-overwrite/lefthook.yml +2 -1
  92. package/rails/create-only/.simplecov +16 -14
  93. package/rails/create-only/spec/spec_helper.rb +2 -0
  94. package/scripts/two-channel-couplings.json +31 -7
  95. package/scripts/verify-npm-advisories-4333.mjs +166 -0
  96. package/scripts/verify-rails-tooling.rb +175 -0
  97. package/typescript/copy-overwrite/.prettierignore +2 -0
  98. package/typescript/create-only/stryker.conf.json +2 -0
  99. package/typescript/package-lisa/package.lisa.json +10 -6
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Run with the consumer bundle, Ruby 3.4, and an empty owned scratch directory:
4
+ # bundle exec ruby scripts/verify-rails-tooling.rb MODE TEMPLATE_ROOT SCRATCH
5
+ # Modes: bounds, configuration, coverage, coverage-negative,
6
+ # coverage-line-negative, matchers, matchers-negative, security,
7
+ # security-negative, lint, lint-negative, helper-lint.
8
+ # This bounded probe never boots Rails or connects to a database. The packaged
9
+ # Rails/MySQL journey remains a separate acceptance check.
10
+ require "fileutils"
11
+ require "json"
12
+
13
+ SELECTED = {
14
+ "brakeman" => "8.1.0",
15
+ "database_consistency" => "3.0.14",
16
+ "rack-mini-profiler" => "5.0.0",
17
+ "rspec-rails" => "8.0.4",
18
+ "rubocop-capybara" => "3.0.0",
19
+ "rubocop-yard" => "1.3.0",
20
+ "shoulda-matchers" => "8.0.1",
21
+ "simplecov" => "1.3.2"
22
+ }.freeze
23
+
24
+ mode, template_root, scratch = ARGV
25
+ abort "Expected MODE TEMPLATE_ROOT SCRATCH" unless ARGV.length == 3
26
+ template_root = File.realpath(template_root)
27
+ scratch = File.realpath(scratch)
28
+ abort "Scratch must be empty" unless Dir.children(scratch).empty?
29
+
30
+ def copy_template(root, relative, destination)
31
+ FileUtils.mkdir_p(File.dirname(destination))
32
+ FileUtils.cp(File.join(root, relative), destination)
33
+ end
34
+
35
+ Dir.chdir(scratch) do
36
+ case mode
37
+ when "bounds"
38
+ require "bundler"
39
+ definition = Bundler::Dsl.evaluate(File.join(template_root, "rails/copy-overwrite/Gemfile.lisa"), nil, {})
40
+ failures = SELECTED.filter_map do |name, selected|
41
+ dependency = definition.dependencies.find { |item| item.name == name }
42
+ abort "Missing family #{name}" unless dependency
43
+ actual = Gem.loaded_specs.fetch(name).version
44
+ abort "Wrong selected version #{name}: #{actual}" unless actual.to_s == selected
45
+ next_major = Gem::Version.new("#{actual.segments.first + 1}.0.0")
46
+ abort "Untested next major admitted for #{name}" if dependency.requirement.satisfied_by?(next_major)
47
+ "#{name}: #{dependency.requirement} rejects #{actual}" unless dependency.requirement.satisfied_by?(actual)
48
+ end
49
+ abort failures.join("\n") unless failures.empty?
50
+ { "shoulda-matchers" => "8.0.0", "simplecov" => "1.3.1" }.each do |name, old_patch|
51
+ requirement = definition.dependencies.find { |item| item.name == name }.requirement
52
+ abort "Pre-fix patch admitted for #{name}" if requirement.satisfied_by?(Gem::Version.new(old_patch))
53
+ end
54
+ puts JSON.generate(marker: "RAILS_TOOL_BOUNDS_ACCEPTED", versions: SELECTED)
55
+ when "configuration"
56
+ copy_template(template_root, "rails/create-only/.simplecov", ".simplecov")
57
+ require "simplecov/no_defaults"
58
+ require "simplecov"
59
+ SimpleCov.deprecations :raise
60
+ load ".simplecov"
61
+ abort "Configuration must not start coverage" if Coverage.running?
62
+ puts "SIMPLECOV_CONFIGURATION_ACCEPTED"
63
+ when "coverage", "coverage-negative", "coverage-line-negative"
64
+ copy_template(template_root, "rails/create-only/.simplecov", ".simplecov")
65
+ copy_template(template_root, "rails/create-only/spec/spec_helper.rb", "spec/spec_helper.rb")
66
+ FileUtils.mkdir_p("app/models")
67
+ File.write("app/models/coverage_probe.rb", <<~RUBY)
68
+ class CoverageProbe
69
+ def greeting(value)
70
+ if value == :hello
71
+ "welcome"
72
+ else
73
+ "goodbye"
74
+ end
75
+ end
76
+ def detail
77
+ text = "detail"
78
+ text.upcase
79
+ text.reverse
80
+ end
81
+ end
82
+ RUBY
83
+ require "rspec/core"
84
+ load "spec/spec_helper.rb"
85
+ SimpleCov.deprecations :raise
86
+ abort "Coverage must start in the helper" unless Coverage.running?
87
+ SimpleCov.merging false
88
+ require File.join(scratch, "app/models/coverage_probe")
89
+ probe = CoverageProbe.new
90
+ abort "Wrong exercised result" unless probe.greeting(:hello) == "welcome"
91
+ if mode != "coverage-negative"
92
+ abort "Wrong second branch" unless probe.greeting(:other) == "goodbye"
93
+ end
94
+ abort "Wrong line-control result" unless probe.detail == "liated" if mode == "coverage"
95
+ puts "COVERAGE_PROBE_EXECUTED"
96
+ when "matchers", "matchers-negative"
97
+ copy_template(template_root, "rails/create-only/.simplecov", ".simplecov")
98
+ copy_template(template_root, "rails/create-only/spec/spec_helper.rb", "spec/spec_helper.rb")
99
+ FileUtils.mkdir_p("app/models")
100
+ FileUtils.mkdir_p("spec/models")
101
+ File.write("app/models/matcher_probe.rb", <<~RUBY)
102
+ class MatcherProbe
103
+ include ActiveModel::Model
104
+ attr_accessor :name
105
+ #{'validates :name, presence: true' if mode == "matchers"}
106
+ end
107
+ RUBY
108
+ File.write("spec/models/matcher_probe_spec.rb", <<~RUBY)
109
+ require "spec_helper"
110
+ require "active_model"
111
+ require "shoulda/matchers"
112
+ Shoulda::Matchers.configure do |config|
113
+ config.integrate do |with|
114
+ with.test_framework :rspec
115
+ with.library :active_model
116
+ end
117
+ end
118
+ require File.join(Dir.pwd, "app/models/matcher_probe")
119
+ RSpec.describe MatcherProbe, type: :model do
120
+ it { is_expected.to validate_presence_of(:name) }
121
+ end
122
+ RUBY
123
+ require "rspec/core"
124
+ exit RSpec::Core::Runner.run(["--format", "documentation", "spec/models/matcher_probe_spec.rb"])
125
+ when "security", "security-negative"
126
+ FileUtils.mkdir_p(["app/controllers", "app/models", "config"])
127
+ File.write("Gemfile", "source 'https://rubygems.org'\ngem 'rails', '= 8.1.4'\n")
128
+ File.write("config/application.rb", "require 'rails/all'\nmodule ToolingProbe\nclass Application < Rails::Application\nconfig.load_defaults 8.1\nend\nend\n")
129
+ File.write("config/routes.rb", "Rails.application.routes.draw { resources :probe_records }\n")
130
+ File.write("app/controllers/application_controller.rb", "class ApplicationController < ActionController::Base\nend\n")
131
+ File.write("app/models/probe_record.rb", "class ProbeRecord < ActiveRecord::Base\nend\n")
132
+ query = if mode == "security-negative"
133
+ 'ProbeRecord.where("name = \'#{params[:name]}\'")'
134
+ else
135
+ "ProbeRecord.where(name: params[:name])"
136
+ end
137
+ File.write("app/controllers/probe_records_controller.rb", "class ProbeRecordsController < ApplicationController\n def index\n #{query}\n end\nend\n")
138
+ require "brakeman"
139
+ tracker = Brakeman.run(app_path: scratch, quiet: true, print_report: false, run_checks: ["CheckSQL"])
140
+ abort "No SQL check executed" unless tracker.checks.checks_run.include?("SQL")
141
+ abort "No model/controller inspected" if tracker.models.empty? || tracker.controllers.empty?
142
+ warnings = tracker.checks.all_warnings.select { |warning| warning.warning_type == "SQL Injection" }
143
+ puts JSON.generate(marker: "BRAKEMAN_SQL_CONTROL", checks: tracker.checks.checks_run, warnings: warnings.length, models: tracker.models.length, controllers: tracker.controllers.length)
144
+ exit(warnings.empty? ? 0 : 1)
145
+ when "helper-lint"
146
+ copy_template(template_root, "rails/copy-overwrite/.rubocop.yml", ".rubocop.yml")
147
+ [".rubocop_todo.yml", "rubocop.thresholds.yml", ".rubocop.local.yml"].each do |name|
148
+ copy_template(template_root, "rails/create-only/#{name}", name)
149
+ end
150
+ ["spec/spec_helper.rb", "spec/rails_helper.rb"].each do |name|
151
+ copy_template(template_root, "rails/create-only/#{name}", name)
152
+ end
153
+ require "rubocop"
154
+ exit RuboCop::CLI.new.run(["--format", "json", "--cache", "false", "spec/spec_helper.rb", "spec/rails_helper.rb"])
155
+ when "lint", "lint-negative"
156
+ copy_template(template_root, "rails/copy-overwrite/.rubocop.yml", ".rubocop.yml")
157
+ [".rubocop_todo.yml", "rubocop.thresholds.yml", ".rubocop.local.yml"].each do |name|
158
+ copy_template(template_root, "rails/create-only/#{name}", name)
159
+ end
160
+ FileUtils.mkdir_p("spec/features")
161
+ negative = mode == "lint-negative"
162
+ File.write("spec/features/tooling_probe_spec.rb", <<~RUBY)
163
+ #{negative ? 'all(".thing").first' : 'find(".thing")'}
164
+
165
+ # @param #{negative ? "wrong" : "name"} [String] the name
166
+ def greeting(name)
167
+ name
168
+ end
169
+ RUBY
170
+ require "rubocop"
171
+ exit RuboCop::CLI.new.run(["--only", "Capybara/FindAllFirst,YARD/MismatchName", "--format", "json", "--cache", "false", "spec/features/tooling_probe_spec.rb"])
172
+ else
173
+ abort "Unknown mode #{mode}"
174
+ end
175
+ end
@@ -86,9 +86,11 @@ scripts/lisa-destructive-guard.mjs
86
86
  scripts/lisa-environment-prepare.mjs
87
87
  scripts/lisa-floor-collisions.mjs
88
88
  scripts/lisa-gates.mjs
89
+ scripts/lisa-history-secrets.mjs
89
90
  scripts/lisa-lint-staged-preflight.mjs
90
91
  scripts/lisa-mutation.mjs
91
92
  scripts/lisa-postinstall.mjs
93
+ scripts/lisa-rails-prepush.mjs
92
94
  scripts/lisa-reconcile-policy.mjs
93
95
  scripts/lisa-run-gates.mjs
94
96
  scripts/lisa-schema-validate.mjs
@@ -1,6 +1,8 @@
1
1
  {
2
2
  "$schema": "./node_modules/@stryker-mutator/core/schema/stryker-schema.json",
3
3
  "testRunner": "vitest",
4
+ "_pluginsComment": "Resolve the declared runner explicitly for isolated dependency layouts instead of relying on sibling package discovery.",
5
+ "plugins": ["@stryker-mutator/vitest-runner"],
4
6
  "reporters": ["clear-text", "progress", "html"],
5
7
  "coverageAnalysis": "perTest",
6
8
  "ignoreStatic": true,
@@ -31,8 +31,8 @@
31
31
  "typecheck:lisa": "node scripts/lib/worktree-dependencies.mjs && tsc --noEmit"
32
32
  },
33
33
  "devDependencies": {
34
- "eslint-plugin-oxlint": "^1.62.0",
35
- "oxlint": "^1.62.0",
34
+ "eslint-plugin-oxlint": "1.62.0",
35
+ "oxlint": "1.62.0",
36
36
  "oxlint-tsgolint": "^0.24.0",
37
37
  "@stryker-mutator/core": "^9.0.0",
38
38
  "@stryker-mutator/vitest-runner": "^9.0.0",
@@ -49,7 +49,9 @@
49
49
  "vite": "^8.3.2",
50
50
  "ws": ">=8.21.0",
51
51
  "form-data": ">=4.0.6",
52
- "systeminformation": ">=5.31.7"
52
+ "systeminformation": ">=5.31.7",
53
+ "qs": "^6.16.0",
54
+ "deepmerge-ts": "^8.0.1"
53
55
  },
54
56
  "overrides": {
55
57
  "@isaacs/brace-expansion": "^5.0.1",
@@ -62,16 +64,18 @@
62
64
  "vite": "^8.3.2",
63
65
  "ws": ">=8.21.0",
64
66
  "form-data": ">=4.0.6",
65
- "systeminformation": ">=5.31.7"
67
+ "systeminformation": ">=5.31.7",
68
+ "qs": "^6.16.0",
69
+ "deepmerge-ts": "^8.0.1"
66
70
  }
67
71
  },
68
72
  "defaults": {
69
73
  "devDependencies": {
70
74
  "@ast-grep/cli": "^0.40.4",
71
75
  "@vitest/coverage-v8": "^4.1.11",
72
- "eslint": "^9.39.0",
76
+ "eslint": "^9.39.5",
73
77
  "husky": "^8.0.0",
74
- "prettier": "^3.3.3",
78
+ "prettier": "3.8.0",
75
79
  "typescript": "^6.0.3",
76
80
  "vitest": "^4.1.11"
77
81
  },