@codyswann/lisa 3.48.6 → 3.49.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 (68) hide show
  1. package/dist/cli/doctor-hook-copy-parity.d.ts +8 -0
  2. package/dist/cli/doctor-hook-copy-parity.d.ts.map +1 -0
  3. package/dist/cli/doctor-hook-copy-parity.js +121 -0
  4. package/dist/cli/doctor-hook-copy-parity.js.map +1 -0
  5. package/dist/cli/doctor.d.ts.map +1 -1
  6. package/dist/cli/doctor.js +6 -0
  7. package/dist/cli/doctor.js.map +1 -1
  8. package/dist/core/hook-copy-parity.d.ts +81 -0
  9. package/dist/core/hook-copy-parity.d.ts.map +1 -0
  10. package/dist/core/hook-copy-parity.js +111 -0
  11. package/dist/core/hook-copy-parity.js.map +1 -0
  12. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  13. package/dist/core/upstream-evidence-manifest.js +14 -2
  14. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  15. package/package.json +1 -1
  16. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  17. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  18. package/plugins/lisa-agy/plugin.json +1 -1
  19. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  20. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  21. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  22. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  28. package/plugins/lisa-expo-agy/plugin.json +1 -1
  29. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  33. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  34. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  37. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  38. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  39. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  43. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  44. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  48. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  49. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  53. package/plugins/lisa-rails-agy/plugin.json +1 -1
  54. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  58. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  59. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  63. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  64. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  66. package/scripts/check-derived-artifacts.mjs +22 -4
  67. package/scripts/generate-upstream-evidence-manifest.mjs +10 -1
  68. package/scripts/lib/upstream-manifest-staleness.mjs +235 -0
@@ -0,0 +1,8 @@
1
+ import type { DoctorCheck } from "./doctor.js";
2
+ /**
3
+ * Report hooks whose tracked copies declare different features.
4
+ * @param targetPath - Project path to inspect
5
+ * @returns Doctor check result
6
+ */
7
+ export declare function checkHookCopyParity(targetPath: string): Promise<DoctorCheck>;
8
+ //# sourceMappingURL=doctor-hook-copy-parity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-hook-copy-parity.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-hook-copy-parity.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA2E/C;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,WAAW,CAAC,CAgDtB"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Report sibling copies of one git hook that disagree about a declared feature.
3
+ *
4
+ * Answers a question no other check asks. The Lisa-owned artifact check
5
+ * (`doctor-lisa-owned-artifacts`) compares one destination path in a project
6
+ * against the copies the package ships for it — "is this host running a stale
7
+ * copy of what we shipped?". This asks the orthogonal question: "do the copies
8
+ * inside ONE tree agree with each other?" A second copy at a different path,
9
+ * in a directory the package does not ship, is invisible to the first check by
10
+ * construction and was invisible for four weeks (CodySwannGT/lisa#2847).
11
+ *
12
+ * Naturally quiet in a host project, where each hook has exactly one tracked
13
+ * copy and there is nothing to disagree.
14
+ * @module cli/doctor-hook-copy-parity
15
+ */
16
+ import { execFile } from "node:child_process";
17
+ import { readFile } from "node:fs/promises";
18
+ import * as path from "node:path";
19
+ import { promisify } from "node:util";
20
+ import { declaredHookFeatures, deriveHookCopyGroups, describeHookCopyFinding, findHookCopyDrift, } from "../core/hook-copy-parity.js";
21
+ const CHECK_NAME = "Hook copies agree?";
22
+ const GIT_TIMEOUT_MS = 10_000;
23
+ const GIT_MAX_BUFFER_BYTES = 8 * 1024 * 1024;
24
+ const MAX_REPORTED_FINDINGS = 5;
25
+ const run = promisify(execFile);
26
+ /**
27
+ * Every path git tracks in a checkout.
28
+ * @param targetPath - Project path to inspect
29
+ * @returns Repo-relative tracked paths, or undefined when git cannot answer
30
+ */
31
+ async function trackedPaths(targetPath) {
32
+ try {
33
+ const { stdout } = await run("git", ["ls-files", "-z"], {
34
+ cwd: targetPath,
35
+ maxBuffer: GIT_MAX_BUFFER_BYTES,
36
+ timeout: GIT_TIMEOUT_MS,
37
+ });
38
+ return stdout.split("\0").filter(entry => entry.length > 0);
39
+ }
40
+ catch {
41
+ return undefined;
42
+ }
43
+ }
44
+ /**
45
+ * Read one hook copy and extract what it declares.
46
+ *
47
+ * A copy that cannot be read is reported as declaring nothing rather than
48
+ * dropped: dropping it would let an unreadable copy silently leave the roster,
49
+ * which is the failure this check exists to prevent.
50
+ * @param targetPath - Project root
51
+ * @param relative - Repo-relative path of the copy
52
+ * @returns The copy and its declared features
53
+ */
54
+ async function readHookCopy(targetPath, relative) {
55
+ try {
56
+ const source = await readFile(path.join(targetPath, relative), "utf8");
57
+ return { path: relative, features: declaredHookFeatures(source) };
58
+ }
59
+ catch {
60
+ return { path: relative, features: [] };
61
+ }
62
+ }
63
+ /**
64
+ * Collect every disagreement between sibling copies of a hook in one checkout.
65
+ * @param targetPath - Project path to inspect
66
+ * @param paths - Repo-relative tracked paths
67
+ * @returns Findings across every hook with more than one copy
68
+ */
69
+ async function collectFindings(targetPath, paths) {
70
+ const groups = deriveHookCopyGroups(paths).filter(group => group.paths.length > 1);
71
+ const perGroup = await Promise.all(groups.map(async (group) => {
72
+ const copies = await Promise.all(group.paths.map(relative => readHookCopy(targetPath, relative)));
73
+ return findHookCopyDrift(group.hook, copies);
74
+ }));
75
+ return perGroup.flat();
76
+ }
77
+ /**
78
+ * Report hooks whose tracked copies declare different features.
79
+ * @param targetPath - Project path to inspect
80
+ * @returns Doctor check result
81
+ */
82
+ export async function checkHookCopyParity(targetPath) {
83
+ const paths = await trackedPaths(targetPath);
84
+ if (paths === undefined) {
85
+ return {
86
+ name: CHECK_NAME,
87
+ status: "warn",
88
+ detail: "Could not list tracked files, so sibling hook copies were not compared. " +
89
+ "This is not a pass — run `lisa doctor` from inside a git checkout",
90
+ };
91
+ }
92
+ const multiCopy = deriveHookCopyGroups(paths).filter(group => group.paths.length > 1);
93
+ if (multiCopy.length === 0) {
94
+ return {
95
+ name: CHECK_NAME,
96
+ status: "ok",
97
+ detail: "No hook has more than one tracked copy",
98
+ };
99
+ }
100
+ const findings = await collectFindings(targetPath, paths);
101
+ if (findings.length === 0) {
102
+ const copies = multiCopy.reduce((total, group) => total + group.paths.length, 0);
103
+ return {
104
+ name: CHECK_NAME,
105
+ status: "ok",
106
+ detail: `${copies} tracked copies across ${multiCopy.length} hook(s) declare the same features`,
107
+ };
108
+ }
109
+ const shown = findings
110
+ .slice(0, MAX_REPORTED_FINDINGS)
111
+ .map(describeHookCopyFinding);
112
+ const more = findings.length > MAX_REPORTED_FINDINGS
113
+ ? ` (+${findings.length - MAX_REPORTED_FINDINGS} more)`
114
+ : "";
115
+ return {
116
+ name: CHECK_NAME,
117
+ status: "fail",
118
+ detail: `${findings.length} feature(s) differ between copies of the same hook: ${shown.join("; ")}${more}`,
119
+ };
120
+ }
121
+ //# sourceMappingURL=doctor-hook-copy-parity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-hook-copy-parity.js","sourceRoot":"","sources":["../../src/cli/doctor-hook-copy-parity.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAmBnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAMzD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,mDAAmD;AACnD,KAAK,YAAY,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AAO3C,oCAAoC;AACpC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,sCAAsC;AACtC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED,wCAAwC;AACxC,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wCAAwC;AACxC,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,OAAO,KAAK,CAAC;IACxB,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;CACjD;AAaD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,EAChD,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,WAAW,CAAC,CAyBtB;AA4MD;;;;;;GAMG;AACH,wBAAsB,SAAS,CAC7B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,aAAa,EACtB,YAAY,GAAE,OAAO,CAAC,kBAAkB,CAAM,GAC7C,OAAO,CAAC,YAAY,CAAC,CA2EvB"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAmBnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAOzD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,mDAAmD;AACnD,KAAK,YAAY,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AAO3C,oCAAoC;AACpC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,sCAAsC;AACtC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB;;;;;;;;;;;;OAYG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED,wCAAwC;AACxC,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wCAAwC;AACxC,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,OAAO,KAAK,CAAC;IACxB,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;CACjD;AAaD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,EAChD,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,WAAW,CAAC,CAyBtB;AA4MD;;;;;;GAMG;AACH,wBAAsB,SAAS,CAC7B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,aAAa,EACtB,YAAY,GAAE,OAAO,CAAC,kBAAkB,CAAM,GAC7C,OAAO,CAAC,YAAY,CAAC,CAgFvB"}
@@ -23,6 +23,7 @@ import { checkApplyFailure } from "./doctor-apply-failure.js";
23
23
  import { renderDoctorResult } from "./doctor-render.js";
24
24
  import { checkSkipJobsMigration } from "./doctor-skip-jobs-migration.js";
25
25
  import { checkTraceabilityGate } from "./doctor-traceability-gate.js";
26
+ import { checkHookCopyParity } from "./doctor-hook-copy-parity.js";
26
27
  import { checkWorktreeHygiene } from "./doctor-worktree-hygiene.js";
27
28
  import { checkWorktreeWorkAtRisk } from "./doctor-worktree-work-at-risk.js";
28
29
  import { STARTERS } from "./starters.js";
@@ -306,6 +307,11 @@ export async function runDoctor(targetPath, options, dependencies = {}) {
306
307
  // Static answer to a runtime failure that is deliberately silent: an
307
308
  // incomplete serialize opt-in warns at 2am on a green job and nowhere else.
308
309
  await checkSerializeLegsContract(resolvedTarget),
310
+ // Sibling copies of one hook inside THIS tree, which the Lisa-owned
311
+ // artifact check cannot see: its axis is host copy vs shipped package copy
312
+ // for one destination, so a second copy at another path is outside it by
313
+ // construction (CodySwannGT/lisa#2847).
314
+ await checkHookCopyParity(resolvedTarget),
309
315
  await checkWorktreeHygiene(resolvedTarget),
310
316
  // Immediately after the count check, and deliberately separate from it.
311
317
  // Hygiene answers "how many checkouts is every crawler walking past"; this
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Sibling copies of one git hook, derived from the tree rather than written down.
3
+ *
4
+ * Three tracked copies of the pre-push hook existed in this repository; every
5
+ * test that could have caught the third drifting six commits behind was named a
6
+ * parity test and hardcoded a two-entry roster that omitted it. Each such test
7
+ * proves parity across the copies it happens to list, so "the copies agree"
8
+ * silently meant "the copies someone remembered agree" the moment a third copy
9
+ * appeared (CodySwannGT/lisa#2847).
10
+ *
11
+ * The roster here is derived from the set of tracked paths, so a copy added
12
+ * tomorrow joins every check that consumes it without anyone editing a list.
13
+ *
14
+ * The feature axis is the gate ids a hook declares through `lisa_gate_covers`.
15
+ * That marker is the one machine-readable link between a built-in hook step and
16
+ * the gate registry entry that can stand it down, so a copy missing an id is a
17
+ * copy in which that property is either unprovable or ungovernable — the exact
18
+ * shape the drift took. Comparing whole bytes instead would be useless: sibling
19
+ * copies legitimately differ (Lisa's own hook is not its shipped template), so a
20
+ * byte check would be permanently red and would prove nothing about behaviour.
21
+ * @module core/hook-copy-parity
22
+ */
23
+ /** One tracked copy of a hook, with the features it declares. */
24
+ export interface HookCopy {
25
+ /** Repo-relative path of this copy. */
26
+ readonly path: string;
27
+ /** Features this copy declares, sorted. */
28
+ readonly features: readonly string[];
29
+ }
30
+ /** Every tracked copy of one hook name. */
31
+ export interface HookCopyGroup {
32
+ /** The hook's file name, e.g. `pre-push`. */
33
+ readonly hook: string;
34
+ /** Repo-relative paths of every tracked copy, sorted. */
35
+ readonly paths: readonly string[];
36
+ }
37
+ /** A feature some copies of a hook declare and others do not. */
38
+ export interface HookCopyFinding {
39
+ /** The hook name the disagreeing copies share. */
40
+ readonly hook: string;
41
+ /** The feature that is present in one copy and absent from another. */
42
+ readonly feature: string;
43
+ /** Copies that declare the feature, sorted. */
44
+ readonly present: readonly string[];
45
+ /** Copies that do not, sorted. */
46
+ readonly absent: readonly string[];
47
+ }
48
+ /**
49
+ * Group tracked paths into the hooks they are copies of.
50
+ *
51
+ * Identity is the file name under `.husky/`: `.husky/pre-push` and
52
+ * `any/prefix/.husky/pre-push` are two copies of one logical hook. Paths that
53
+ * are not hooks are ignored, and a hook with a single copy still gets a group —
54
+ * callers decide what a one-copy group means.
55
+ * @param trackedPaths - Repo-relative paths of every tracked file
56
+ * @returns One group per hook name, sorted by hook name
57
+ */
58
+ export declare function deriveHookCopyGroups(trackedPaths: readonly string[]): readonly HookCopyGroup[];
59
+ /**
60
+ * The features one hook's source declares.
61
+ * @param source - Full text of the hook
62
+ * @returns Declared feature ids, sorted and de-duplicated
63
+ */
64
+ export declare function declaredHookFeatures(source: string): readonly string[];
65
+ /**
66
+ * Report every feature that sibling copies of one hook disagree about.
67
+ *
68
+ * A hook with fewer than two copies can never disagree, and a feature no copy
69
+ * declares is not a feature, so both cases produce nothing.
70
+ * @param hook - The hook name these copies share
71
+ * @param copies - Every tracked copy of that hook
72
+ * @returns One finding per disputed feature, sorted by feature
73
+ */
74
+ export declare function findHookCopyDrift(hook: string, copies: readonly HookCopy[]): readonly HookCopyFinding[];
75
+ /**
76
+ * One operator-readable line per finding.
77
+ * @param finding - A disputed feature
78
+ * @returns A sentence naming the feature and both sides
79
+ */
80
+ export declare function describeHookCopyFinding(finding: HookCopyFinding): string;
81
+ //# sourceMappingURL=hook-copy-parity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-copy-parity.d.ts","sourceRoot":"","sources":["../../src/core/hook-copy-parity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,iEAAiE;AACjE,MAAM,WAAW,QAAQ;IACvB,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED,2CAA2C;AAC3C,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yDAAyD;IACzD,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,iEAAiE;AACjE,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,kCAAkC;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAuBD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,SAAS,MAAM,EAAE,GAC9B,SAAS,aAAa,EAAE,CAc1B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAQtE;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,QAAQ,EAAE,GAC1B,SAAS,eAAe,EAAE,CAgB5B;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAKxE"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Sibling copies of one git hook, derived from the tree rather than written down.
3
+ *
4
+ * Three tracked copies of the pre-push hook existed in this repository; every
5
+ * test that could have caught the third drifting six commits behind was named a
6
+ * parity test and hardcoded a two-entry roster that omitted it. Each such test
7
+ * proves parity across the copies it happens to list, so "the copies agree"
8
+ * silently meant "the copies someone remembered agree" the moment a third copy
9
+ * appeared (CodySwannGT/lisa#2847).
10
+ *
11
+ * The roster here is derived from the set of tracked paths, so a copy added
12
+ * tomorrow joins every check that consumes it without anyone editing a list.
13
+ *
14
+ * The feature axis is the gate ids a hook declares through `lisa_gate_covers`.
15
+ * That marker is the one machine-readable link between a built-in hook step and
16
+ * the gate registry entry that can stand it down, so a copy missing an id is a
17
+ * copy in which that property is either unprovable or ungovernable — the exact
18
+ * shape the drift took. Comparing whole bytes instead would be useless: sibling
19
+ * copies legitimately differ (Lisa's own hook is not its shipped template), so a
20
+ * byte check would be permanently red and would prove nothing about behaviour.
21
+ * @module core/hook-copy-parity
22
+ */
23
+ /** Matches any tracked path that is a file directly inside a `.husky` directory. */
24
+ const HUSKY_HOOK = /(?:^|\/)\.husky\/([^/]+)$/u;
25
+ /**
26
+ * Matches a `lisa_gate_covers` call and captures its arguments.
27
+ *
28
+ * Anchored at the start of a shell word so the helper's own definition
29
+ * (`lisa_gate_covers() {`) and its body never register as declarations — only a
30
+ * call site passing at least one gate id does.
31
+ */
32
+ const GATE_COVERS = /(?:^|\s)lisa_gate_covers((?:[ \t]+[A-Za-z0-9][\w-]*)+)/gmu;
33
+ /**
34
+ * Alphabetical order that does not depend on the ambient locale's default.
35
+ * @param left - First name
36
+ * @param right - Second name
37
+ * @returns Negative, zero, or positive per `String.localeCompare`
38
+ */
39
+ const byName = (left, right) => left.localeCompare(right);
40
+ /**
41
+ * Group tracked paths into the hooks they are copies of.
42
+ *
43
+ * Identity is the file name under `.husky/`: `.husky/pre-push` and
44
+ * `any/prefix/.husky/pre-push` are two copies of one logical hook. Paths that
45
+ * are not hooks are ignored, and a hook with a single copy still gets a group —
46
+ * callers decide what a one-copy group means.
47
+ * @param trackedPaths - Repo-relative paths of every tracked file
48
+ * @returns One group per hook name, sorted by hook name
49
+ */
50
+ export function deriveHookCopyGroups(trackedPaths) {
51
+ const located = trackedPaths.flatMap(trackedPath => {
52
+ const hook = HUSKY_HOOK.exec(trackedPath)?.[1];
53
+ return hook === undefined ? [] : [{ hook, path: trackedPath }];
54
+ });
55
+ return [...new Set(located.map(entry => entry.hook))]
56
+ .sort(byName)
57
+ .map(hook => ({
58
+ hook,
59
+ paths: located
60
+ .filter(entry => entry.hook === hook)
61
+ .map(entry => entry.path)
62
+ .sort(byName),
63
+ }));
64
+ }
65
+ /**
66
+ * The features one hook's source declares.
67
+ * @param source - Full text of the hook
68
+ * @returns Declared feature ids, sorted and de-duplicated
69
+ */
70
+ export function declaredHookFeatures(source) {
71
+ const declared = [...source.matchAll(GATE_COVERS)].flatMap(match => (match[1] ?? "")
72
+ .trim()
73
+ .split(/[ \t]+/u)
74
+ .map(id => `gate:${id}`));
75
+ return [...new Set(declared)].sort(byName);
76
+ }
77
+ /**
78
+ * Report every feature that sibling copies of one hook disagree about.
79
+ *
80
+ * A hook with fewer than two copies can never disagree, and a feature no copy
81
+ * declares is not a feature, so both cases produce nothing.
82
+ * @param hook - The hook name these copies share
83
+ * @param copies - Every tracked copy of that hook
84
+ * @returns One finding per disputed feature, sorted by feature
85
+ */
86
+ export function findHookCopyDrift(hook, copies) {
87
+ if (copies.length < 2)
88
+ return [];
89
+ const union = [...new Set(copies.flatMap(copy => [...copy.features]))].sort(byName);
90
+ return union.flatMap(feature => {
91
+ const present = copies
92
+ .filter(copy => copy.features.includes(feature))
93
+ .map(copy => copy.path)
94
+ .sort(byName);
95
+ const absent = copies
96
+ .filter(copy => !copy.features.includes(feature))
97
+ .map(copy => copy.path)
98
+ .sort(byName);
99
+ return absent.length === 0 ? [] : [{ hook, feature, present, absent }];
100
+ });
101
+ }
102
+ /**
103
+ * One operator-readable line per finding.
104
+ * @param finding - A disputed feature
105
+ * @returns A sentence naming the feature and both sides
106
+ */
107
+ export function describeHookCopyFinding(finding) {
108
+ return (`${finding.hook}: ${finding.feature} is declared by ` +
109
+ `${finding.present.join(", ")} but absent from ${finding.absent.join(", ")}`);
110
+ }
111
+ //# sourceMappingURL=hook-copy-parity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-copy-parity.js","sourceRoot":"","sources":["../../src/core/hook-copy-parity.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"upstream-evidence-manifest.d.ts","sourceRoot":"","sources":["../../src/core/upstream-evidence-manifest.ts"],"names":[],"mappings":"AACA,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA82EpE,CAAC;AAEL,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CA42OjE,CAAC;AAEL,sFAAsF;AACtF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAk6I/D,CAAC"}
1
+ {"version":3,"file":"upstream-evidence-manifest.d.ts","sourceRoot":"","sources":["../../src/core/upstream-evidence-manifest.ts"],"names":[],"mappings":"AACA,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAg3EpE,CAAC;AAEL,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAu3OjE,CAAC;AAEL,sFAAsF;AACtF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAk6I/D,CAAC"}
@@ -1068,7 +1068,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
1068
1068
  "scripts/build-plugins.sh": "00a3207bb5a485bfee80fb71be6e9577979fd156b15a85517e88a2f9261bc9f4",
1069
1069
  "scripts/check-conflict-markers.mjs": "3a2ab8dde9deab3e8ee750d5678b6653751abad2eb8f961500585ba38f502047",
1070
1070
  "scripts/check-delivery-deletion-conflicts.mjs": "e7fe0064ad82a4dba17436657630a46891568a3d18930eb172fe9ee3f54196aa",
1071
- "scripts/check-derived-artifacts.mjs": "62c895baffad41c25fa919b798a53e2e969163897bcbb09b0e26345c61f61320",
1071
+ "scripts/check-derived-artifacts.mjs": "86cca46aa7f055ae149b5a378d56d2c4e5dbbbe48e020b79883e21cae50c5956",
1072
1072
  "scripts/check-duplicate-versions.mjs": "26b26351dd2735dfd8d9a2436b89e876ce2ed93871d0b264f611215dd03d70ae",
1073
1073
  "scripts/check-learnings-budget.ts": "007430c2d6938efcc79ccbfd5717ebe2c7cf66b4de9a21a3e67b8db7f3600349",
1074
1074
  "scripts/check-plugins-sync.sh": "3a99cbff0e8ec5e7c944690eae003a6d51b51c85436d77bd37faea4d553728af",
@@ -1094,7 +1094,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
1094
1094
  "scripts/generate-copilot-plugin-artifacts.mjs": "7af923118c49101e6ba46da73a8eee8aee9b797e074618aa5345913e638d7cdb",
1095
1095
  "scripts/generate-cursor-plugin-artifacts.mjs": "45d3bde7b6c55310f0d9436dd68a1bdeefb6fa817be4d15ef745421b39a2cf47",
1096
1096
  "scripts/generate-lisa-owned-hash-ledger.mjs": "4e7a6dd9325fff77faec49c1dcbf8a8cfeb987052eeed89885deb4f7b0a107bc",
1097
- "scripts/generate-upstream-evidence-manifest.mjs": "005ff3ef61e63aab9ed466a3e545df5e8f46e369fdcff94b6e7723161148bc82",
1097
+ "scripts/generate-upstream-evidence-manifest.mjs": "a33bd0ee344782a9b2f400f5adfeecd9e7e201b61b073a9e85cc69311b8721e0",
1098
1098
  "scripts/github-status-check.sh": "c6a4a13ff5cf689fcbd7a6aca718f9e7d46d54ccb6687f662b055c1ca20e792f",
1099
1099
  "scripts/install-claude-plugins.sh": "0e96ebbae1e59304bb432286eccba38900a6008b80f2c53a1ec2c95801d4087c",
1100
1100
  "scripts/internal-agy-skill-policy.json": "c2ce87d2eeebfdc9f24d6486425c010cf9289376f8a459f4767ca22d2bf8670d",
@@ -1108,6 +1108,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
1108
1108
  "scripts/lib/per-agent-hook-filter.mjs": "04ea61ea616614fb545024f98ab27fb08af3f0331da06bb60943d6262e264000",
1109
1109
  "scripts/lib/reusable-workflow-contract.d.mts": "791f01b55dd7a6b5d9a5f4cb9c44167caa146c2fc3c31a2ae4c2d8a350adc2f1",
1110
1110
  "scripts/lib/reusable-workflow-contract.mjs": "134ee2a327290f066f1eb318b5ed53c711557c3e10ed462c00ff5c97cfb20863",
1111
+ "scripts/lib/upstream-manifest-staleness.mjs": "c69fc5ba10228b7f4f8d0068db27ee8a289143094fa8718b14af83f4af31f76d",
1111
1112
  "scripts/lisa-assert-eas-profile.mjs": "624e40d7f33ca17208fc6b7a19320a785cff19da5d2ff8062b67a432b2a34022",
1112
1113
  "scripts/lisa-commit-and-pr-local.sh": "605409c3ce6ec38ad3275604291a1ceae98f7807a605654263bc14f811c03903",
1113
1114
  "scripts/lisa-commit-msg-gates.mjs": "f961cb70a525e7b0a94b8ca7a76d1e2bb5b1929d5477417e159dbf58312ce0d8",
@@ -1211,6 +1212,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
1211
1212
  /** Exact paths tracked by the public Lisa repository at generation time. */
1212
1213
  export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
1213
1214
  ".agents/rules/never-name-downstream-projects.md": true,
1215
+ ".agents/rules/regenerating-derived-artifacts.md": true,
1214
1216
  ".agents/skills/claude-code-action/SKILL.md": true,
1215
1217
  ".agents/skills/claude-code-action/references/inputs.md": true,
1216
1218
  ".agents/skills/harness-parity-council/SKILL.md": true,
@@ -7068,6 +7070,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7068
7070
  "scripts/lib/per-agent-hook-filter.mjs": true,
7069
7071
  "scripts/lib/reusable-workflow-contract.d.mts": true,
7070
7072
  "scripts/lib/reusable-workflow-contract.mjs": true,
7073
+ "scripts/lib/upstream-manifest-staleness.mjs": true,
7071
7074
  "scripts/lisa-assert-eas-profile.mjs": true,
7072
7075
  "scripts/lisa-commit-and-pr-local.sh": true,
7073
7076
  "scripts/lisa-commit-msg-gates.mjs": true,
@@ -7108,6 +7111,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7108
7111
  "src/cli/doctor-apply-failure.ts": true,
7109
7112
  "src/cli/doctor-apply-freshness.ts": true,
7110
7113
  "src/cli/doctor-gate-recommendation.ts": true,
7114
+ "src/cli/doctor-hook-copy-parity.ts": true,
7111
7115
  "src/cli/doctor-kane.ts": true,
7112
7116
  "src/cli/doctor-learnings-ledger.ts": true,
7113
7117
  "src/cli/doctor-learnings-merge-driver.ts": true,
@@ -7285,6 +7289,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7285
7289
  "src/core/downstream-references.ts": true,
7286
7290
  "src/core/git-service.ts": true,
7287
7291
  "src/core/guard-capabilities.ts": true,
7292
+ "src/core/hook-copy-parity.ts": true,
7288
7293
  "src/core/host-rules-pointer.ts": true,
7289
7294
  "src/core/index.ts": true,
7290
7295
  "src/core/instruction-files-migration.ts": true,
@@ -7544,8 +7549,10 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7544
7549
  "tests/fixtures/verification/v2_structurally_invalid_claims.json": true,
7545
7550
  "tests/fixtures/wiki-safety/allowed-contacts.md": true,
7546
7551
  "tests/fixtures/wiki-safety/redaction-source.md": true,
7552
+ "tests/helpers/__fixtures__/margin-guard-case.ts": true,
7547
7553
  "tests/helpers/__fixtures__/wiki-status-fixture.ts": true,
7548
7554
  "tests/helpers/cpu-budget.ts": true,
7555
+ "tests/helpers/hook-roster.ts": true,
7549
7556
  "tests/helpers/io-latency-budget.ts": true,
7550
7557
  "tests/helpers/nightly-e2e-gate-harness.ts": true,
7551
7558
  "tests/helpers/nightly-e2e-reporting-harness.ts": true,
@@ -7625,6 +7632,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7625
7632
  "tests/integration/support/reusable-workflow-scopes.ts": true,
7626
7633
  "tests/integration/threshold-ratchet-gate-fail-closed.test.ts": true,
7627
7634
  "tests/integration/tracked-source-nul-bytes.test.ts": true,
7635
+ "tests/support/git-executable.ts": true,
7628
7636
  "tests/support/work-item-cli.ts": true,
7629
7637
  "tests/unit/agy/block-no-verify-agy.test.ts": true,
7630
7638
  "tests/unit/agy/mcp-collect.test.ts": true,
@@ -7636,6 +7644,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7636
7644
  "tests/unit/cli/doctor-apply-failure.test.ts": true,
7637
7645
  "tests/unit/cli/doctor-apply-freshness.test.ts": true,
7638
7646
  "tests/unit/cli/doctor-gate-recommendation.test.ts": true,
7647
+ "tests/unit/cli/doctor-hook-copy-parity.test.ts": true,
7639
7648
  "tests/unit/cli/doctor-kane.test.ts": true,
7640
7649
  "tests/unit/cli/doctor-learnings-ledger.test.ts": true,
7641
7650
  "tests/unit/cli/doctor-learnings-merge-driver.test.ts": true,
@@ -7825,6 +7834,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7825
7834
  "tests/unit/core/bootstrap-environment.test.ts": true,
7826
7835
  "tests/unit/core/fs-extra-namespace-callsites.test.ts": true,
7827
7836
  "tests/unit/core/fs-extra-namespace-members.test.ts": true,
7837
+ "tests/unit/core/hook-copy-parity.test.ts": true,
7828
7838
  "tests/unit/core/host-rules-parity.test.ts": true,
7829
7839
  "tests/unit/core/host-rules-pointer.test.ts": true,
7830
7840
  "tests/unit/core/instruction-files-migration.test.ts": true,
@@ -7887,6 +7897,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
7887
7897
  "tests/unit/health/gitignore.test.ts": true,
7888
7898
  "tests/unit/health/package-surfaces.test.ts": true,
7889
7899
  "tests/unit/health/storage.test.ts": true,
7900
+ "tests/unit/helpers/io-latency-budget.test.ts": true,
7890
7901
  "tests/unit/hooks/block-direct-issue-create-bypasses.test.ts": true,
7891
7902
  "tests/unit/hooks/block-direct-issue-create-declarations.test.ts": true,
7892
7903
  "tests/unit/hooks/block-direct-issue-create-missing-interpreter.test.ts": true,
@@ -8088,6 +8099,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
8088
8099
  "tests/unit/scripts/threshold-ratchet-wiring.test.ts": true,
8089
8100
  "tests/unit/scripts/threshold-ratchet.test.ts": true,
8090
8101
  "tests/unit/scripts/upstream-evidence-manifest.test.ts": true,
8102
+ "tests/unit/scripts/upstream-manifest-staleness.test.ts": true,
8091
8103
  "tests/unit/scripts/vacuous-required-checks.test.ts": true,
8092
8104
  "tests/unit/scripts/verification-coverage.test.ts": true,
8093
8105
  "tests/unit/scripts/work-item-backlink-exactness.test.ts": true,