@codyswann/lisa 3.33.5 → 3.33.7

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 (145) hide show
  1. package/all/copy-overwrite/scripts/check-state-classification.mjs +18 -4
  2. package/all/copy-overwrite/scripts/lisa-gates.mjs +47 -46
  3. package/all/copy-overwrite/scripts/lisa-run-gates.mjs +3 -2
  4. package/all/copy-overwrite/scripts/lisa-work-item.mjs +284 -2
  5. package/dist/configs/eslint/base.d.ts +21 -0
  6. package/dist/configs/eslint/base.d.ts.map +1 -1
  7. package/dist/configs/eslint/base.js +78 -2
  8. package/dist/configs/eslint/base.js.map +1 -1
  9. package/dist/configs/eslint/cdk.d.ts.map +1 -1
  10. package/dist/configs/eslint/cdk.js +5 -1
  11. package/dist/configs/eslint/cdk.js.map +1 -1
  12. package/dist/configs/eslint/expo.d.ts.map +1 -1
  13. package/dist/configs/eslint/expo.js +5 -1
  14. package/dist/configs/eslint/expo.js.map +1 -1
  15. package/dist/configs/eslint/harper-fabric.d.ts.map +1 -1
  16. package/dist/configs/eslint/harper-fabric.js +6 -1
  17. package/dist/configs/eslint/harper-fabric.js.map +1 -1
  18. package/dist/configs/eslint/nestjs.d.ts.map +1 -1
  19. package/dist/configs/eslint/nestjs.js +5 -1
  20. package/dist/configs/eslint/nestjs.js.map +1 -1
  21. package/dist/configs/eslint/phaser.d.ts.map +1 -1
  22. package/dist/configs/eslint/phaser.js +6 -1
  23. package/dist/configs/eslint/phaser.js.map +1 -1
  24. package/dist/configs/eslint/typescript.d.ts +2 -2
  25. package/dist/configs/eslint/typescript.d.ts.map +1 -1
  26. package/dist/configs/eslint/typescript.js +6 -2
  27. package/dist/configs/eslint/typescript.js.map +1 -1
  28. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  29. package/dist/core/lisa-owned-hash-ledger.js +12 -0
  30. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  31. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  32. package/dist/core/upstream-evidence-manifest.js +36 -35
  33. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  34. package/expo/copy-overwrite/scripts/bdd/baseline.mjs +11 -4
  35. package/expo/copy-overwrite/scripts/bdd/discover.mjs +12 -6
  36. package/expo/copy-overwrite/scripts/bdd/waivers.mjs +7 -4
  37. package/expo/copy-overwrite/scripts/bdd-matrix.mjs +1 -0
  38. package/expo/copy-overwrite/scripts/check-bdd-coverage.mjs +26 -17
  39. package/expo/copy-overwrite/scripts/check-e2e-coverage.mjs +12 -8
  40. package/package.json +1 -1
  41. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  43. package/plugins/lisa/.codex-plugin/skills/lisa-git-submit-pr/SKILL.md +11 -4
  44. package/plugins/lisa/.codex-plugin/skills/lisa-github-sync/SKILL.md +7 -2
  45. package/plugins/lisa/.codex-plugin/skills/lisa-implement/SKILL.md +1 -1
  46. package/plugins/lisa/.codex-plugin/skills/lisa-jira-sync/SKILL.md +7 -2
  47. package/plugins/lisa/.codex-plugin/skills/lisa-linear-sync/SKILL.md +7 -2
  48. package/plugins/lisa/.codex-plugin/skills/lisa-tracker-sync/SKILL.md +7 -2
  49. package/plugins/lisa/skills/lisa-git-submit-pr/SKILL.md +11 -4
  50. package/plugins/lisa/skills/lisa-github-sync/SKILL.md +7 -2
  51. package/plugins/lisa/skills/lisa-implement/SKILL.md +1 -1
  52. package/plugins/lisa/skills/lisa-jira-sync/SKILL.md +7 -2
  53. package/plugins/lisa/skills/lisa-linear-sync/SKILL.md +7 -2
  54. package/plugins/lisa/skills/lisa-tracker-sync/SKILL.md +7 -2
  55. package/plugins/lisa-agy/plugin.json +1 -1
  56. package/plugins/lisa-agy/skills/lisa-git-submit-pr/SKILL.md +11 -4
  57. package/plugins/lisa-agy/skills/lisa-github-sync/SKILL.md +7 -2
  58. package/plugins/lisa-agy/skills/lisa-implement/SKILL.md +1 -1
  59. package/plugins/lisa-agy/skills/lisa-jira-sync/SKILL.md +7 -2
  60. package/plugins/lisa-agy/skills/lisa-linear-sync/SKILL.md +7 -2
  61. package/plugins/lisa-agy/skills/lisa-tracker-sync/SKILL.md +7 -2
  62. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  64. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  65. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-copilot/skills/lisa-git-submit-pr/SKILL.md +11 -4
  69. package/plugins/lisa-copilot/skills/lisa-github-sync/SKILL.md +7 -2
  70. package/plugins/lisa-copilot/skills/lisa-implement/SKILL.md +1 -1
  71. package/plugins/lisa-copilot/skills/lisa-jira-sync/SKILL.md +7 -2
  72. package/plugins/lisa-copilot/skills/lisa-linear-sync/SKILL.md +7 -2
  73. package/plugins/lisa-copilot/skills/lisa-tracker-sync/SKILL.md +7 -2
  74. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-cursor/skills/lisa-git-submit-pr/SKILL.md +11 -4
  76. package/plugins/lisa-cursor/skills/lisa-github-sync/SKILL.md +7 -2
  77. package/plugins/lisa-cursor/skills/lisa-implement/SKILL.md +1 -1
  78. package/plugins/lisa-cursor/skills/lisa-jira-sync/SKILL.md +7 -2
  79. package/plugins/lisa-cursor/skills/lisa-linear-sync/SKILL.md +7 -2
  80. package/plugins/lisa-cursor/skills/lisa-tracker-sync/SKILL.md +7 -2
  81. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  83. package/plugins/lisa-expo-agy/plugin.json +1 -1
  84. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  85. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  88. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  89. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  90. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  91. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  93. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  94. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  95. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  96. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  97. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  98. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  99. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  100. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  101. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  102. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  103. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  104. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  105. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  106. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  107. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  108. package/plugins/lisa-rails-agy/plugin.json +1 -1
  109. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  110. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  111. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  112. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  113. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  114. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  115. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  116. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  117. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  118. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  119. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  120. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  121. package/plugins/src/base/skills/lisa-git-submit-pr/SKILL.md +11 -4
  122. package/plugins/src/base/skills/lisa-github-sync/SKILL.md +7 -2
  123. package/plugins/src/base/skills/lisa-implement/SKILL.md +1 -1
  124. package/plugins/src/base/skills/lisa-jira-sync/SKILL.md +7 -2
  125. package/plugins/src/base/skills/lisa-linear-sync/SKILL.md +7 -2
  126. package/plugins/src/base/skills/lisa-tracker-sync/SKILL.md +7 -2
  127. package/scripts/check-conflict-markers.mjs +1 -1
  128. package/scripts/check-required-check-promotions.mjs +8 -4
  129. package/scripts/detect-stale-workflow-inputs.mjs +1 -3
  130. package/scripts/fix-namespace-test-assertions.mjs +1 -1
  131. package/scripts/generate-agy-plugin-artifacts.mjs +12 -7
  132. package/scripts/generate-codex-plugin-artifacts.mjs +14 -9
  133. package/scripts/generate-copilot-plugin-artifacts.mjs +1 -1
  134. package/scripts/generate-cursor-plugin-artifacts.mjs +2 -2
  135. package/scripts/generate-upstream-evidence-manifest.mjs +1 -1
  136. package/scripts/lisa-assert-eas-profile.mjs +3 -3
  137. package/scripts/plugin-parity-drift.mjs +29 -13
  138. package/scripts/plugin-routing-validate.mjs +8 -2
  139. package/scripts/update-node-version.ts +7 -3
  140. package/scripts/verify-health-agentic-built.mjs +27 -20
  141. package/scripts/verify-health-consumer-built.mjs +7 -3
  142. package/scripts/verify-health-deterministic-built.mjs +24 -19
  143. package/typescript/copy-overwrite/eslint.ignore.config.json +0 -2
  144. package/typescript/copy-overwrite/scripts/check-nightly-e2e-health.mjs +9 -4
  145. package/typescript/copy-overwrite/scripts/lisa-mutation.mjs +1 -3
@@ -113,9 +113,25 @@ const PERSISTENCE_SIGNALS = Object.freeze([
113
113
  { kind: "schema-definition", pattern: /(^|\/)db\/schema\.[cm]?[jt]s$/iu },
114
114
  ]);
115
115
 
116
+ // The `CREATE TABLE` grammar, one clause per name. Written as fragments rather
117
+ // than one literal because the literal was unreadable — the alternations are
118
+ // SQL's, and loosening any of them into a wildcard would make the subtraction
119
+ // detector match statements that are not entity declarations.
120
+ /** `CREATE [UNLOGGED|TEMPORARY|TEMP|GLOBAL|LOCAL] ...` modifier run. */
121
+ const CREATE_MODIFIERS =
122
+ "(?:unlogged\\s+|temporary\\s+|temp\\s+|global\\s+|local\\s+)*";
123
+ /** The object kinds that declare durable state. */
124
+ const CREATE_OBJECT_KIND = "(?:materialized\\s+view|table|view)";
125
+ /** Optional `IF NOT EXISTS` guard. */
126
+ const OPTIONAL_IF_NOT_EXISTS = "(?:if\\s+not\\s+exists\\s+)?";
127
+ /** A possibly schema-qualified, possibly quoted identifier. */
128
+ const ENTITY_NAME = '([\\w."`[\\]]+)';
129
+
116
130
  /** `CREATE TABLE`-shaped declarations the subtraction detector recognizes. */
117
- const CREATE_ENTITY_PATTERN =
118
- /create\s+(?:unlogged\s+|temporary\s+|temp\s+|global\s+|local\s+)*(?:materialized\s+view|table|view)\s+(?:if\s+not\s+exists\s+)?([\w."`[\]]+)/giu;
131
+ const CREATE_ENTITY_PATTERN = new RegExp(
132
+ `create\\s+${CREATE_MODIFIERS}${CREATE_OBJECT_KIND}\\s+${OPTIONAL_IF_NOT_EXISTS}${ENTITY_NAME}`,
133
+ "giu"
134
+ );
119
135
 
120
136
  /**
121
137
  * Read a JSON file, returning a discriminated result rather than throwing.
@@ -277,11 +293,9 @@ export function compareInventory({
277
293
  }) {
278
294
  const findings = [];
279
295
  const entities = contract.entities ?? [];
280
- const byBareName = new Map();
281
296
  const classified = new Map();
282
297
  for (const entity of entities) {
283
298
  classified.set(entity.id, entity);
284
- byBareName.set(bareName(entity.id), entity);
285
299
  }
286
300
  const waived = new Map(
287
301
  (contract.waivers ?? []).map(waiver => [waiver.id, waiver])
@@ -71,17 +71,24 @@ export const LEVELS = ["required", "optional", "off"];
71
71
  /** What to do when a gate reports success without evidence of work. */
72
72
  export const HOLLOW_RESPONSES = ["report", "wait", "block"];
73
73
 
74
+ // Moment names, named once. They appear in a dozen moment lists below; a
75
+ // literal repeated that many times is one typo away from a gate that silently
76
+ // never runs, and there is no test that can tell "gate not configured for this
77
+ // moment" from "moment misspelled".
78
+ const SESSION_START = "session-start";
79
+ const PRE_TOOL = "pre-tool";
80
+ const COMMIT = "commit";
81
+ const PUSH = "push";
82
+ const PULL_REQUEST = "pull-request";
83
+ const PRE_DEPLOY = "pre-deploy";
84
+ const POST_DEPLOY = "post-deploy";
85
+ const CONTINUOUS = "continuous";
86
+
74
87
  /** Fixed moments. Two more families take an environment suffix. */
75
- export const MOMENTS = [
76
- "session-start",
77
- "pre-tool",
78
- "commit",
79
- "push",
80
- "pull-request",
81
- ];
88
+ export const MOMENTS = [SESSION_START, PRE_TOOL, COMMIT, PUSH, PULL_REQUEST];
82
89
 
83
90
  /** Moment families that take an `:<environment>` suffix. */
84
- export const MOMENT_FAMILIES = ["pre-deploy", "post-deploy", "continuous"];
91
+ export const MOMENT_FAMILIES = [PRE_DEPLOY, POST_DEPLOY, CONTINUOUS];
85
92
 
86
93
  /**
87
94
  * Moments that gate a *state* rather than a change.
@@ -99,7 +106,7 @@ export const MOMENT_FAMILIES = ["pre-deploy", "post-deploy", "continuous"];
99
106
  * new cases against a stable one. It applies equally to a CVE published today,
100
107
  * which makes yesterday's dependency scan wrong with no change at all.
101
108
  */
102
- export const STATE_FAMILIES = ["continuous"];
109
+ export const STATE_FAMILIES = [CONTINUOUS];
103
110
 
104
111
  /** Keys on a gate entry that are settings rather than moments. */
105
112
  export const GATE_FIELDS = new Set(["run", "needs", "task"]);
@@ -130,19 +137,12 @@ export const GATE_FIELDS = new Set(["run", "needs", "task"]);
130
137
  /** Prefix marking a gate, or a config key, that this project invented. */
131
138
  export const CUSTOM_PREFIX = "x-";
132
139
 
133
- const COMMIT_ONWARD = [
134
- "commit",
135
- "push",
136
- "pull-request",
137
- "pre-deploy",
138
- "post-deploy",
139
- ];
140
- const PUSH_ONWARD = ["push", "pull-request", "pre-deploy", "post-deploy"];
141
- const PR_ONWARD = ["pull-request", "pre-deploy", "post-deploy"];
142
- const PR_ONLY = ["pull-request"];
143
- const DEPLOY_ONLY = ["pre-deploy", "post-deploy", "continuous"];
144
- const CONTINUOUS_ONLY = ["continuous"];
145
- const SESSION_ONWARD = ["session-start", ...COMMIT_ONWARD];
140
+ const COMMIT_ONWARD = [COMMIT, PUSH, PULL_REQUEST, PRE_DEPLOY, POST_DEPLOY];
141
+ const PUSH_ONWARD = [PUSH, PULL_REQUEST, PRE_DEPLOY, POST_DEPLOY];
142
+ const PR_ONWARD = [PULL_REQUEST, PRE_DEPLOY, POST_DEPLOY];
143
+ const PR_ONLY = [PULL_REQUEST];
144
+ const DEPLOY_ONLY = [PRE_DEPLOY, POST_DEPLOY, CONTINUOUS];
145
+ const SESSION_ONWARD = [SESSION_START, ...COMMIT_ONWARD];
146
146
 
147
147
  /**
148
148
  * Lisa's canonical gates.
@@ -231,14 +231,14 @@ export const REGISTRY = Object.freeze({
231
231
  label: "🎭 Playwright E2E Tests",
232
232
  summary: "Browser journeys pass end to end.",
233
233
  task: "test:e2e",
234
- moments: [...PR_ONWARD, "continuous"],
234
+ moments: [...PR_ONWARD, CONTINUOUS],
235
235
  work: "specs run",
236
236
  },
237
237
  "e2e-native": {
238
238
  label: "📱 Maestro Native E2E",
239
239
  summary: "Native device journeys pass end to end.",
240
240
  task: "test:e2e:native",
241
- moments: [...PR_ONWARD, "continuous"],
241
+ moments: [...PR_ONWARD, CONTINUOUS],
242
242
  work: "flows run",
243
243
  },
244
244
  // ---------------------------------------------------------------------
@@ -268,7 +268,7 @@ export const REGISTRY = Object.freeze({
268
268
  summary:
269
269
  "The environment reset exists, and its guard cannot be bypassed by calling it directly.",
270
270
  task: "environment:reset:verify",
271
- moments: [...PR_ONWARD, "continuous"],
271
+ moments: [...PR_ONWARD, CONTINUOUS],
272
272
  work: "refusals proved",
273
273
  },
274
274
  "environment-reseed": {
@@ -276,7 +276,7 @@ export const REGISTRY = Object.freeze({
276
276
  summary:
277
277
  "The environment reseed exists, and its guard cannot be bypassed by calling it directly.",
278
278
  task: "environment:reseed:verify",
279
- moments: [...PR_ONWARD, "continuous"],
279
+ moments: [...PR_ONWARD, CONTINUOUS],
280
280
  work: "refusals proved",
281
281
  },
282
282
  "generative-testing": {
@@ -288,7 +288,7 @@ export const REGISTRY = Object.freeze({
288
288
  // re-running one suite against every change explores far less of the input
289
289
  // space than generating new cases against a stable one." A property suite
290
290
  // pinned to the per-change gate re-walks the same ground forever.
291
- moments: [...PR_ONWARD, "continuous"],
291
+ moments: [...PR_ONWARD, CONTINUOUS],
292
292
  work: "cases generated",
293
293
  },
294
294
  "structural-rules": {
@@ -322,14 +322,14 @@ export const REGISTRY = Object.freeze({
322
322
  task: "security:audit",
323
323
  // Continuous matters most here: a CVE published today makes yesterday's
324
324
  // green wrong with no change to trigger a re-scan.
325
- moments: [...PUSH_ONWARD, "continuous"],
325
+ moments: [...PUSH_ONWARD, CONTINUOUS],
326
326
  work: "manifests scanned",
327
327
  },
328
328
  "static-security": {
329
329
  label: "🔍 Static Security Analysis",
330
330
  summary: "Static analysis finds no security defect.",
331
331
  task: "security:sast",
332
- moments: [...PR_ONWARD, "continuous"],
332
+ moments: [...PR_ONWARD, CONTINUOUS],
333
333
  work: "files analysed",
334
334
  },
335
335
  "runtime-web-vulnerability": {
@@ -349,7 +349,7 @@ export const REGISTRY = Object.freeze({
349
349
  label: "👁️ Code Review",
350
350
  summary: "The change was reviewed by something that read it.",
351
351
  task: "review:local",
352
- moments: ["push", "pull-request"],
352
+ moments: [PUSH, PULL_REQUEST],
353
353
  },
354
354
  "performance-budget": {
355
355
  label: "⚡ Performance Budget",
@@ -768,9 +768,9 @@ function validateGate(id, gate) {
768
768
  ...Object.keys(INTERCEPTORS),
769
769
  ]);
770
770
  return [
771
- `gates."${id}" is not a gate Lisa knows` +
772
- (near ? `. Did you mean "${near}"?` : "") +
773
- ` Prefix a gate of your own with "${CUSTOM_PREFIX}" — Lisa will run ` +
771
+ `gates."${id}" is not a gate Lisa knows${
772
+ near ? `. Did you mean "${near}"?` : ""
773
+ } Prefix a gate of your own with "${CUSTOM_PREFIX}" — Lisa will run ` +
774
774
  `it without pretending to understand it.`,
775
775
  ];
776
776
  }
@@ -834,7 +834,7 @@ function validateMoment(id, moment, value, known, interceptor, gateRun) {
834
834
  );
835
835
  }
836
836
  if (entry.await) {
837
- if (["commit", "push", "session-start", "pre-tool"].includes(moment)) {
837
+ if ([COMMIT, PUSH, SESSION_START, PRE_TOOL].includes(moment)) {
838
838
  problems.push(
839
839
  `gates."${id}"."${moment}" awaits "${entry.await}", but there is no ` +
840
840
  `pull request yet for a signal to post against. An awaited check ` +
@@ -953,8 +953,9 @@ export function validatePolicy(policy) {
953
953
  if (!Object.hasOwn(POLICY_SCHEMA, section)) {
954
954
  const near = nearest(section, Object.keys(POLICY_SCHEMA));
955
955
  problems.push(
956
- `policy."${section}" is not a policy section Lisa knows` +
957
- (near ? `. Did you mean "${near}"?` : "")
956
+ `policy."${section}" is not a policy section Lisa knows${
957
+ near ? `. Did you mean "${near}"?` : ""
958
+ }`
958
959
  );
959
960
  continue;
960
961
  }
@@ -967,8 +968,9 @@ export function validatePolicy(policy) {
967
968
  if (!expected) {
968
969
  const near = nearest(field, Object.keys(POLICY_SCHEMA[section]));
969
970
  problems.push(
970
- `policy.${section}."${field}" is not a setting Lisa manages` +
971
- (near ? `. Did you mean "${near}"?` : "")
971
+ `policy.${section}."${field}" is not a setting Lisa manages${
972
+ near ? `. Did you mean "${near}"?` : ""
973
+ }`
972
974
  );
973
975
  continue;
974
976
  }
@@ -1012,10 +1014,9 @@ export function auditConfigKeys(config) {
1012
1014
  findings.push({
1013
1015
  key,
1014
1016
  level: "warn",
1015
- message:
1016
- `${key} is not a key Lisa reads` +
1017
- (near ? `. Did you mean "${near}"?` : "") +
1018
- ` Nothing consumes it, so whatever it was meant to configure is unset.`,
1017
+ message: `${key} is not a key Lisa reads${
1018
+ near ? `. Did you mean "${near}"?` : ""
1019
+ } Nothing consumes it, so whatever it was meant to configure is unset.`,
1019
1020
  });
1020
1021
  }
1021
1022
  return findings;
@@ -1050,7 +1051,7 @@ export function resolveMoment({
1050
1051
  // for a real moment; it is refused only for one that cannot exist.
1051
1052
  if (!isMoment(moment)) {
1052
1053
  throw new Error(
1053
- `"${moment}" ${unknownMomentMessage(moment)} ` + knownMomentsMessage()
1054
+ `"${moment}" ${unknownMomentMessage(moment)} ${knownMomentsMessage()}`
1054
1055
  );
1055
1056
  }
1056
1057
  assertValidMomentKeys(gates);
@@ -1184,7 +1185,7 @@ export function needsAt({ gates, moment }) {
1184
1185
  */
1185
1186
  export function contextsFor(gates, options = {}) {
1186
1187
  const {
1187
- moment = "pull-request",
1188
+ moment = PULL_REQUEST,
1188
1189
  workflowName = "🔍 Quality Checks",
1189
1190
  previousLabels = [],
1190
1191
  } = options;
@@ -1347,7 +1348,7 @@ function main() {
1347
1348
  }
1348
1349
 
1349
1350
  if (command === "needs") {
1350
- const moment = flag("moment") ?? "session-start";
1351
+ const moment = flag("moment") ?? SESSION_START;
1351
1352
  console.log(JSON.stringify(needsAt({ gates, moment }), null, 2));
1352
1353
  return;
1353
1354
  }
@@ -1360,7 +1361,7 @@ function main() {
1360
1361
  console.log(
1361
1362
  JSON.stringify(
1362
1363
  contextsFor(gates, {
1363
- moment: flag("moment") ?? "pull-request",
1364
+ moment: flag("moment") ?? PULL_REQUEST,
1364
1365
  workflowName: flag("workflow") ?? "🔍 Quality Checks",
1365
1366
  previousLabels,
1366
1367
  }),
@@ -305,8 +305,9 @@ function summarise(result) {
305
305
  `(optional), ${result.skipped.length} not provable here`;
306
306
  lines.push(
307
307
  `${failedOptional.length ? "⚠️ " : "✅"} ${result.moment}: ${counts}, ` +
308
- `of ${result.total} gate(s) declared.` +
309
- (failedOptional.length ? " See the optional failure(s) above." : "")
308
+ `of ${result.total} gate(s) declared.${
309
+ failedOptional.length ? " See the optional failure(s) above." : ""
310
+ }`
310
311
  );
311
312
  return lines;
312
313
  }
@@ -25,6 +25,14 @@ const RELEASE_SUBJECT =
25
25
  /^chore\(release\): \d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)? \[skip ci\]$/;
26
26
  const ZERO_OID = /^0+$/;
27
27
  const MARKER = "[lisa-pr-link]";
28
+ /**
29
+ * The command that establishes the ticket-side backlink.
30
+ *
31
+ * Named in every refusal that the backlink is missing. A validator that
32
+ * reports "no verified backlink" without the remedy sends the reader looking
33
+ * for a producer that, until this command existed, was prose in a SKILL.md.
34
+ */
35
+ const BACKLINK_COMMAND = "node scripts/lisa-work-item.mjs backlink";
28
36
  /**
29
37
  * The prefix only — an anchored, fixed-length literal with no quantifier, so
30
38
  * it cannot backtrack. The ReDoS was never here; it was in the `\s*(.+?)\s*$`
@@ -1217,6 +1225,247 @@ export function textContainsBacklink(value, prUrl) {
1217
1225
  return false;
1218
1226
  }
1219
1227
 
1228
+ /**
1229
+ * The managed backlink comment's body.
1230
+ *
1231
+ * One line, and the whole body — so establishing the backlink is a whole-body
1232
+ * replace rather than an append, which is what makes a rerun converge instead
1233
+ * of accumulating. Nothing else is carried here on purpose: the milestone and
1234
+ * the merge SHA belong to the vendor sync skills' progress notes, and putting
1235
+ * them in this body would make every rerun a content change.
1236
+ * @param {string} prUrl Pull request URL.
1237
+ * @returns {string} The comment body.
1238
+ */
1239
+ function backlinkBody(prUrl) {
1240
+ return `${MARKER} ${prUrl}`;
1241
+ }
1242
+
1243
+ /**
1244
+ * Whether a comment payload is Lisa's managed backlink comment.
1245
+ *
1246
+ * Shape-agnostic deliberately: GitHub and Linear return a plain string body,
1247
+ * Jira returns an Atlassian Document Format tree. Serialising covers all three
1248
+ * without a per-provider walker, and the marker is distinctive enough that a
1249
+ * false positive would have to be a comment quoting it verbatim — which is
1250
+ * still Lisa's comment to reuse rather than a second one to add.
1251
+ * @param {unknown} body Comment body in whatever shape the provider returned.
1252
+ * @returns {boolean} True when this is the managed comment.
1253
+ */
1254
+ function carriesMarker(body) {
1255
+ return JSON.stringify(body ?? "").includes(MARKER);
1256
+ }
1257
+
1258
+ /**
1259
+ * Establish the backlink on a GitHub issue.
1260
+ * @param {string} ref Canonical `owner/repo#number` reference.
1261
+ * @param {string} prUrl Pull request URL.
1262
+ * @returns {string} What changed: created, updated, or unchanged.
1263
+ */
1264
+ function githubBacklink(ref, prUrl) {
1265
+ const [repository, number] = ref.split("#");
1266
+ const listing = run(
1267
+ "gh",
1268
+ [
1269
+ "api",
1270
+ "--paginate",
1271
+ `repos/${repository}/issues/${number}/comments?per_page=100`,
1272
+ ],
1273
+ { allowFailure: true }
1274
+ );
1275
+ if (listing.status !== 0) throw githubFailure(listing, ref);
1276
+ const comments = safeJson(listing.stdout, `GitHub comments on ${ref}`);
1277
+ const managed = (Array.isArray(comments) ? comments : []).find(comment =>
1278
+ carriesMarker(comment?.body)
1279
+ );
1280
+ const body = backlinkBody(prUrl);
1281
+ if (managed && managed.body === body) return "unchanged";
1282
+ const [method, endpoint] = managed
1283
+ ? ["PATCH", `repos/${repository}/issues/comments/${managed.id}`]
1284
+ : ["POST", `repos/${repository}/issues/${number}/comments`];
1285
+ run("gh", ["api", "--method", method, endpoint, "--field", `body=${body}`], {
1286
+ error: `could not write the backlink comment on ${ref}`,
1287
+ });
1288
+ return managed ? "updated" : "created";
1289
+ }
1290
+
1291
+ /**
1292
+ * Send one Linear GraphQL document, refusing on either failure surface.
1293
+ *
1294
+ * GraphQL answers an invalid mutation with HTTP 200 and an `errors` array, so
1295
+ * a status-only check reports success for a comment that was never written.
1296
+ * @param {string} token Linear API key.
1297
+ * @param {string} query The document.
1298
+ * @param {object} variables Its variables.
1299
+ * @param {string} context What the call was for, for the message.
1300
+ * @returns {object} The `data` payload.
1301
+ */
1302
+ function linearGraphql(token, query, variables, context) {
1303
+ const result = secureCurl(
1304
+ ["https://api.linear.app/graphql"],
1305
+ [
1306
+ ["request", "POST"],
1307
+ ["header", "Content-Type: application/json"],
1308
+ ["header", `Authorization: ${token}`],
1309
+ ["data-binary", JSON.stringify({ query, variables })],
1310
+ ],
1311
+ { allowFailure: true }
1312
+ );
1313
+ if (result.status !== 0) throw new TrackingError(`${context} failed`);
1314
+ const response = safeJson(result.stdout, context);
1315
+ if (Array.isArray(response.errors) && response.errors.length > 0)
1316
+ throw new TrackingError(
1317
+ `${context} failed: ${response.errors[0]?.message}`
1318
+ );
1319
+ return response.data ?? {};
1320
+ }
1321
+
1322
+ /**
1323
+ * Establish the backlink on a Linear issue.
1324
+ * @param {string} ref Canonical `KEY-123` identifier.
1325
+ * @param {string} prUrl Pull request URL.
1326
+ * @param {object} contract Resolved tracker contract.
1327
+ * @returns {string} What changed: created, updated, or unchanged.
1328
+ */
1329
+ function linearBacklink(ref, prUrl, contract) {
1330
+ const token = readLinearKey(contract.workspace);
1331
+ if (!token)
1332
+ throw new TrackingError(
1333
+ "writing a Linear backlink requires LINEAR_API_KEY or a lisa-linear keychain entry"
1334
+ );
1335
+ const issue = linearGraphql(
1336
+ token,
1337
+ "query($id:String!){issue(id:$id){id comments{nodes{id body}}}}",
1338
+ { id: ref },
1339
+ `Linear issue ${ref} lookup`
1340
+ ).issue;
1341
+ if (!issue?.id)
1342
+ throw new TrackingError(
1343
+ `Linear issue ${ref} does not exist or is inaccessible`
1344
+ );
1345
+ const managed = (issue.comments?.nodes ?? []).find(comment =>
1346
+ carriesMarker(comment?.body)
1347
+ );
1348
+ const body = backlinkBody(prUrl);
1349
+ if (managed && managed.body === body) return "unchanged";
1350
+ if (managed) {
1351
+ linearGraphql(
1352
+ token,
1353
+ "mutation($id:String!,$body:String!){commentUpdate(id:$id,input:{body:$body}){success}}",
1354
+ { body, id: managed.id },
1355
+ `Linear backlink update on ${ref}`
1356
+ );
1357
+ return "updated";
1358
+ }
1359
+ linearGraphql(
1360
+ token,
1361
+ "mutation($id:String!,$body:String!){commentCreate(input:{issueId:$id,body:$body}){success}}",
1362
+ { body, id: issue.id },
1363
+ `Linear backlink comment on ${ref}`
1364
+ );
1365
+ return "created";
1366
+ }
1367
+
1368
+ /**
1369
+ * The managed comment as an Atlassian Document Format tree.
1370
+ *
1371
+ * A single text node, so the marker and the URL land in one string — which is
1372
+ * what `textContainsBacklink` walks the tree looking for. Splitting them across
1373
+ * nodes would write a comment the reader accepts visually and the check
1374
+ * rejects.
1375
+ * @param {string} prUrl Pull request URL.
1376
+ * @returns {object} The ADF document.
1377
+ */
1378
+ function jiraCommentDocument(prUrl) {
1379
+ return {
1380
+ content: [
1381
+ {
1382
+ content: [{ text: backlinkBody(prUrl), type: "text" }],
1383
+ type: "paragraph",
1384
+ },
1385
+ ],
1386
+ type: "doc",
1387
+ version: 1,
1388
+ };
1389
+ }
1390
+
1391
+ /**
1392
+ * Establish the backlink on a Jira ticket.
1393
+ *
1394
+ * Requires API credentials rather than falling back to `acli`: the read path
1395
+ * may degrade to whatever can answer, but a write that silently does not
1396
+ * happen is exactly the failure this command exists to remove.
1397
+ * @param {string} ref Canonical `KEY-123` reference.
1398
+ * @param {string} prUrl Pull request URL.
1399
+ * @param {object} contract Resolved tracker contract.
1400
+ * @returns {string} What changed: created, updated, or unchanged.
1401
+ */
1402
+ function jiraBacklink(ref, prUrl, contract) {
1403
+ const credentials = jiraCredentials(contract);
1404
+ if (!credentials)
1405
+ throw new TrackingError(
1406
+ "writing a Jira backlink requires ATLASSIAN_API_TOKEN/JIRA_API_TOKEN with JIRA_LOGIN and atlassian.cloudId/site"
1407
+ );
1408
+ const issueUrl = `${credentials.baseUrl}/rest/api/3/issue/${encodeURIComponent(ref)}/comment`;
1409
+ const auth = [
1410
+ ["user", `${credentials.login}:${credentials.token}`],
1411
+ ["header", "Accept: application/json"],
1412
+ ];
1413
+ const listing = secureCurl([`${issueUrl}?maxResults=100`], auth, {
1414
+ allowFailure: true,
1415
+ });
1416
+ if (listing.status !== 0)
1417
+ throw new TrackingError(`Jira ticket ${ref} comments are inaccessible`);
1418
+ const existing = safeJson(listing.stdout, `Jira comments on ${ref}`);
1419
+ const managed = (existing.comments ?? []).find(comment =>
1420
+ carriesMarker(comment?.body)
1421
+ );
1422
+ const document = jiraCommentDocument(prUrl);
1423
+ const payload = JSON.stringify({ body: document });
1424
+ if (managed && JSON.stringify(managed.body) === JSON.stringify(document))
1425
+ return "unchanged";
1426
+ secureCurl(
1427
+ [managed ? `${issueUrl}/${encodeURIComponent(managed.id)}` : issueUrl],
1428
+ [
1429
+ ...auth,
1430
+ ["request", managed ? "PUT" : "POST"],
1431
+ ["header", "Content-Type: application/json"],
1432
+ ["data-binary", payload],
1433
+ ],
1434
+ { error: `could not write the backlink comment on ${ref}` }
1435
+ );
1436
+ return managed ? "updated" : "created";
1437
+ }
1438
+
1439
+ /**
1440
+ * Establish the ticket-side backlink, whatever the tracker.
1441
+ *
1442
+ * This is the producer for the comment `assertBacklink` consumes, and it lives
1443
+ * in this file for that reason: the requirement was documented in a SKILL.md
1444
+ * and enforced here, so nothing executable ever wrote it and a required check
1445
+ * failed on a step no command performed.
1446
+ *
1447
+ * Every provider `assertBacklink` reads is written here. A provider that is
1448
+ * not refuses loudly rather than returning quietly, because a silent no-op
1449
+ * here reproduces the original defect one layer down: the command reports
1450
+ * success and the check still fails.
1451
+ * @param {string} ref Canonical work-item reference.
1452
+ * @param {string} prUrl Pull request URL.
1453
+ * @param {object} contract Resolved tracker contract.
1454
+ * @returns {string} What changed: created, updated, or unchanged.
1455
+ */
1456
+ function postBacklink(ref, prUrl, contract) {
1457
+ if (contract.provider === "github") return githubBacklink(ref, prUrl);
1458
+ if (contract.provider === "linear")
1459
+ return linearBacklink(ref, prUrl, contract);
1460
+ if (contract.provider === "jira") return jiraBacklink(ref, prUrl, contract);
1461
+ throw new TrackingError(
1462
+ `no backlink writer for tracker '${contract.provider}'; ` +
1463
+ `github, jira and linear are supported.\nThe Work-Item Traceability check ` +
1464
+ `reads a managed ${MARKER} comment for this provider, so it cannot pass ` +
1465
+ `until a writer exists here — add one rather than posting by hand.`
1466
+ );
1467
+ }
1468
+
1220
1469
  function assertBacklink(
1221
1470
  ref,
1222
1471
  prUrl,
@@ -1502,7 +1751,12 @@ function backlinkAdvice(ref, prUrl, contract) {
1502
1751
  contract.provider === "linear"
1503
1752
  ? `The tracker builds that link from the BRANCH NAME, so a branch carrying no ticket id can never acquire one: no edit to this pull request, its body, or its commits will do it. Fixing it that way needs a NEW branch named for ${ref} and a new pull request from it. `
1504
1753
  : "";
1505
- return `${branchDerived}The one remedy that needs no new branch is a comment on ${ref} containing: ${MARKER} ${prUrl}`;
1754
+ return (
1755
+ `${branchDerived}The one remedy that needs no new branch is the managed comment ` +
1756
+ `\`${MARKER} ${prUrl}\` on ${ref}. Do not post it by hand — run:\n\n` +
1757
+ ` ${BACKLINK_COMMAND} --ref ${ref} --pr-url ${prUrl}\n\n` +
1758
+ `which creates that comment or updates the existing one, so running it twice is safe`
1759
+ );
1506
1760
  }
1507
1761
 
1508
1762
  /**
@@ -1620,6 +1874,33 @@ function bind(args) {
1620
1874
  console.log(`work-item bound: ${ref} (${file})`);
1621
1875
  }
1622
1876
 
1877
+ /**
1878
+ * Establish the ticket-side backlink for one work item and pull request.
1879
+ *
1880
+ * Idempotent by construction — the writer updates the managed comment it finds
1881
+ * rather than adding a second — so this is safe to run on every push, and safe
1882
+ * to rerun after a failure without inspecting what the last run managed to do.
1883
+ * @param {string[]} args CLI arguments.
1884
+ */
1885
+ function backlink(args) {
1886
+ const contract = trackerContract();
1887
+ const supplied = option(args, "--ref", "LISA_WORK_ITEM_REF");
1888
+ const bound = readState(true)?.ref;
1889
+ if (!supplied && !bound) {
1890
+ throw new TrackingError(
1891
+ `${BACKLINK_COMMAND} requires --ref <work-item>, or a worktree binding from \`lisa-work-item.mjs link\``
1892
+ );
1893
+ }
1894
+ const ref = canonicalizeRef(supplied ?? bound, contract);
1895
+ const prUrl =
1896
+ option(args, "--pr-url", "LISA_PR_URL") ??
1897
+ option(args, "--url", "LISA_PR_URL");
1898
+ if (!prUrl)
1899
+ throw new TrackingError(`${BACKLINK_COMMAND} requires --pr-url <url>`);
1900
+ const outcome = postBacklink(ref, prUrl, contract);
1901
+ console.log(`work-item backlink ${outcome} on ${ref}: ${MARKER} ${prUrl}`);
1902
+ }
1903
+
1623
1904
  function prepareCommitMessage(args) {
1624
1905
  const [file, source = ""] = args;
1625
1906
  if (!file)
@@ -1755,12 +2036,13 @@ function main() {
1755
2036
  rmSync(statePath(), { force: true });
1756
2037
  return console.log("work-item binding cleared");
1757
2038
  }
2039
+ if (command === "backlink") return backlink(args);
1758
2040
  if (command === "prepare-commit-msg") return prepareCommitMessage(args);
1759
2041
  if (command === "validate-commit") return validateCommit(args);
1760
2042
  if (command === "validate-push") return validatePush(args);
1761
2043
  if (command === "validate-pr") return validatePr(args);
1762
2044
  throw new TrackingError(
1763
- "Usage: lisa-work-item.mjs link|current|attach-branch|clear|prepare-commit-msg|validate-commit|validate-push|validate-pr" +
2045
+ "Usage: lisa-work-item.mjs link|current|attach-branch|clear|backlink|prepare-commit-msg|validate-commit|validate-push|validate-pr" +
1764
2046
  "\n(`bind` is accepted as an alias for `link`, but some agent harnesses refuse the token `bind` in a command line.)"
1765
2047
  );
1766
2048
  }
@@ -1409,6 +1409,27 @@ export declare const getJsFilesOverride: () => {
1409
1409
  "max-lines-per-function": string;
1410
1410
  };
1411
1411
  };
1412
+ /**
1413
+ * Glob patterns covering the repository-maintenance script tree that Lisa
1414
+ * installs into every consumer (`scripts/`), plus nested `scripts/` trees such
1415
+ * as `projects/<name>/scripts/`. Exported so the coverage test can assert the
1416
+ * shipped `.mjs` paths land inside the same set the override targets.
1417
+ */
1418
+ export declare const scriptsFilePatterns: string[];
1419
+ /**
1420
+ * Standalone-script override — the rule profile for the `scripts/` tree.
1421
+ *
1422
+ * These files are repository-maintenance CLIs invoked by a developer or a CI
1423
+ * runner, not application source and not published library API. They were
1424
+ * previously excluded from linting entirely; that is the defect this override
1425
+ * exists to make survivable. Every rule turned off here is turned off because
1426
+ * it encodes an assumption about application code that a CLI script does not
1427
+ * meet — correctness and bug-finding rules (including the SonarJS rules an
1428
+ * external scanner also runs, e.g. `sonarjs/no-alphabetical-sort`) stay ON,
1429
+ * because those are precisely what the exclusion was hiding.
1430
+ * @returns {object} ESLint flat config object for standalone scripts
1431
+ */
1432
+ export declare const getScriptsFilesOverride: () => Linter.Config;
1412
1433
  /**
1413
1434
  * Shared hooks and components override - relaxes import restrictions.
1414
1435
  * @returns {object} ESLint flat config object for shared files
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/configs/eslint/base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/configs/eslint/base.ts"],"names":[],"mappings":"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"}