@codyswann/lisa 4.15.1 → 4.17.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.
- package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +62 -9
- package/dist/cli/doctor-override-floor-conflicts.d.ts +15 -0
- package/dist/cli/doctor-override-floor-conflicts.d.ts.map +1 -0
- package/dist/cli/doctor-override-floor-conflicts.js +225 -0
- package/dist/cli/doctor-override-floor-conflicts.js.map +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +8 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +2 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/override-floors.d.ts +146 -0
- package/dist/core/override-floors.d.ts.map +1 -0
- package/dist/core/override-floors.js +200 -0
- package/dist/core/override-floors.js.map +1 -0
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +8 -2
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/opencode/plugin-templates/parity-safety-net.sh +62 -9
- package/dist/strategies/package-lisa.d.ts +59 -0
- package/dist/strategies/package-lisa.d.ts.map +1 -1
- package/dist/strategies/package-lisa.js +112 -130
- package/dist/strategies/package-lisa.js.map +1 -1
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/hooks/parity-safety-net.sh +62 -9
- package/plugins/lisa-agy/hooks/parity-safety-net.sh +62 -9
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/hooks/parity-safety-net.sh +62 -9
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/parity-safety-net.sh +62 -9
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/hooks/parity-safety-net.sh +62 -9
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/** package.json sections whose keys are treated as direct dependencies. */
|
|
2
|
+
export declare const DIRECT_DEPENDENCY_SECTIONS: readonly ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"];
|
|
3
|
+
/** package.json sections that carry npm-style version overrides. */
|
|
4
|
+
export declare const OVERRIDE_SECTIONS: readonly ["overrides", "resolutions"];
|
|
5
|
+
/** One of the two npm override sections. */
|
|
6
|
+
export type OverrideSection = (typeof OVERRIDE_SECTIONS)[number];
|
|
7
|
+
/**
|
|
8
|
+
* What rewriting one literal override to `"$name"` would do to its floor.
|
|
9
|
+
*
|
|
10
|
+
* `unprovable` and `widening` are kept apart because they are different
|
|
11
|
+
* operator problems: the first is a range Lisa cannot parse on either side (a
|
|
12
|
+
* git spec, `workspace:*`, an alias), the second is an ordinary semver range
|
|
13
|
+
* that genuinely starts lower than the floor.
|
|
14
|
+
*/
|
|
15
|
+
export type SelfReferenceVerdict = "safe" | "unprovable" | "widening";
|
|
16
|
+
/** One override whose `$name` rewrite would resolve below Lisa's floor. */
|
|
17
|
+
export interface SelfReferenceFloorConflict {
|
|
18
|
+
/** Override section carrying the entry. */
|
|
19
|
+
readonly section: OverrideSection;
|
|
20
|
+
/** Package name. */
|
|
21
|
+
readonly name: string;
|
|
22
|
+
/** Literal override range in the merged manifest — Lisa's floor. */
|
|
23
|
+
readonly floorRange: string;
|
|
24
|
+
/** Direct dependency range `$name` would resolve to. */
|
|
25
|
+
readonly directRange: string;
|
|
26
|
+
/** Why the rewrite is refused. */
|
|
27
|
+
readonly verdict: Exclude<SelfReferenceVerdict, "safe">;
|
|
28
|
+
/**
|
|
29
|
+
* A direct range that has been VERIFIED to satisfy the guard, or null when
|
|
30
|
+
* none could be derived. Never a guess.
|
|
31
|
+
*/
|
|
32
|
+
readonly suggestedDirectRange: string | null;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* What one pass over a merged manifest actually looked at, alongside what it
|
|
36
|
+
* found.
|
|
37
|
+
*
|
|
38
|
+
* The counts are not decoration. A check that inspected nothing and a check
|
|
39
|
+
* that inspected everything and found nothing produce the same empty conflict
|
|
40
|
+
* list, and only the counts tell them apart — so every caller reports them and
|
|
41
|
+
* refuses to call zero inspected a pass.
|
|
42
|
+
*/
|
|
43
|
+
export interface OverrideFloorAudit {
|
|
44
|
+
/** Every top-level entry across `overrides` and `resolutions`. */
|
|
45
|
+
readonly overridesInspected: number;
|
|
46
|
+
/** Those the `$name` normalization guard actually judges. */
|
|
47
|
+
readonly rewritesJudged: number;
|
|
48
|
+
/** Those the guard would refuse. */
|
|
49
|
+
readonly conflicts: readonly SelfReferenceFloorConflict[];
|
|
50
|
+
/** Those the guard would perform, in the order they were read. */
|
|
51
|
+
readonly rewritable: readonly SelfReferenceCandidate[];
|
|
52
|
+
}
|
|
53
|
+
/** One override the `$name` normalization guard judges. */
|
|
54
|
+
export interface SelfReferenceCandidate {
|
|
55
|
+
/** Override section carrying the entry. */
|
|
56
|
+
readonly section: OverrideSection;
|
|
57
|
+
/** Package name. */
|
|
58
|
+
readonly name: string;
|
|
59
|
+
/** Literal override range in the merged manifest. */
|
|
60
|
+
readonly floorRange: string;
|
|
61
|
+
/** Direct dependency range `$name` would resolve to. */
|
|
62
|
+
readonly directRange: string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Narrow an unknown value to a plain object record, returning {} otherwise.
|
|
66
|
+
* @param value - Candidate value
|
|
67
|
+
* @returns The value as a record, or an empty record when it is not a plain object
|
|
68
|
+
*/
|
|
69
|
+
export declare function asRecord(value: unknown): Record<string, unknown>;
|
|
70
|
+
/**
|
|
71
|
+
* Collect the names of every direct dependency declared across a package.json's
|
|
72
|
+
* dependency sections.
|
|
73
|
+
* @param pkg - Merged package.json object
|
|
74
|
+
* @returns Set of direct dependency names
|
|
75
|
+
*/
|
|
76
|
+
export declare function collectDirectDependencyNames(pkg: Record<string, unknown>): Set<string>;
|
|
77
|
+
/**
|
|
78
|
+
* Collect direct dependency ranges by package name.
|
|
79
|
+
* @param pkg - Merged package.json object
|
|
80
|
+
* @returns Package name to string range map
|
|
81
|
+
*/
|
|
82
|
+
export declare function collectDirectDependencyRanges(pkg: Record<string, unknown>): ReadonlyMap<string, string>;
|
|
83
|
+
/**
|
|
84
|
+
* Decide whether an override/resolution entry is a candidate for npm `$name`
|
|
85
|
+
* normalization at all.
|
|
86
|
+
* @param directDeps - Direct dependency names in the merged package
|
|
87
|
+
* @param name - Override/resolution key
|
|
88
|
+
* @param value - Override/resolution value
|
|
89
|
+
* @returns True when the entry is a literal direct-dependency collision
|
|
90
|
+
*/
|
|
91
|
+
export declare function needsSelfReferenceRewrite(directDeps: ReadonlySet<string>, name: string, value: unknown): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* The one predicate behind both the apply's refusal and doctor's report.
|
|
94
|
+
* @remarks
|
|
95
|
+
* Deliberately plain `semver.subset`, with no ceiling normalization. The
|
|
96
|
+
* normalizing variant used by the host-pin branch (`rangeContains` in the
|
|
97
|
+
* package-lisa strategy) can only turn a refusal into an acceptance, and this
|
|
98
|
+
* branch is the one that decides whether a security floor may be resolved
|
|
99
|
+
* DOWNWARDS — so it keeps the stricter reading. Any range that reaches a
|
|
100
|
+
* `widening` verdict here still has a followable way out, because
|
|
101
|
+
* {@link suggestSatisfyingDirectRange} is verified against this same function.
|
|
102
|
+
* @param floorRange - The literal override range being replaced
|
|
103
|
+
* @param directRange - The direct dependency range `$name` would resolve to
|
|
104
|
+
* @returns Whether the rewrite is safe, unprovable, or widening
|
|
105
|
+
*/
|
|
106
|
+
export declare function classifySelfReferenceRewrite(floorRange: string, directRange: string): SelfReferenceVerdict;
|
|
107
|
+
/**
|
|
108
|
+
* Derive a direct dependency range that satisfies the floor, and PROVE it does
|
|
109
|
+
* before handing it to an operator.
|
|
110
|
+
* @remarks
|
|
111
|
+
* The natural suggestion is a caret at the floor's minimum version, because
|
|
112
|
+
* that is what a person writes and what the one already-fixed instance of this
|
|
113
|
+
* defect was fixed with. It is not always right: measured, `^1.18.0` is not a
|
|
114
|
+
* subset of a bounded floor `>=1.18.0 <1.19.0`, and `^0.0.0` is not a subset of
|
|
115
|
+
* `*`. So the caret is a CANDIDATE, tested against
|
|
116
|
+
* {@link classifySelfReferenceRewrite} and discarded when it fails, falling
|
|
117
|
+
* back to the floor range verbatim — which is a subset of itself for any range
|
|
118
|
+
* semver can parse.
|
|
119
|
+
*
|
|
120
|
+
* A floor semver cannot parse yields null. Printing an untested range would be
|
|
121
|
+
* the #3191 failure exactly: advice that sends the operator back into the same
|
|
122
|
+
* refusal.
|
|
123
|
+
* @param floorRange - The literal override range acting as the floor
|
|
124
|
+
* @returns A range verified to satisfy the guard, or null when none exists
|
|
125
|
+
*/
|
|
126
|
+
export declare function suggestSatisfyingDirectRange(floorRange: string): string | null;
|
|
127
|
+
/**
|
|
128
|
+
* Judge every `$name`-rewrite candidate in a merged manifest, collecting ALL
|
|
129
|
+
* conflicts rather than stopping at the first.
|
|
130
|
+
* @remarks
|
|
131
|
+
* The apply throws on the first conflict, which is right for an apply — it is
|
|
132
|
+
* about to write a file and must not. A report has the opposite obligation: an
|
|
133
|
+
* operator who fixes the one package named and re-runs, only to be handed the
|
|
134
|
+
* next one, is being drip-fed a list Lisa already had in full.
|
|
135
|
+
* @param pkg - Merged package.json, as the apply would persist it
|
|
136
|
+
* @returns What was inspected and every conflict found
|
|
137
|
+
*/
|
|
138
|
+
export declare function auditSelfReferenceRewrites(pkg: Record<string, unknown>): OverrideFloorAudit;
|
|
139
|
+
/**
|
|
140
|
+
* The remedy sentence, shared by the apply's refusal and doctor's report so an
|
|
141
|
+
* operator is never told two different things about the same conflict.
|
|
142
|
+
* @param conflict - The conflict to describe
|
|
143
|
+
* @returns One operator-readable sentence naming the exact raise to make
|
|
144
|
+
*/
|
|
145
|
+
export declare function describeSelfReferenceRemedy(conflict: SelfReferenceFloorConflict): string;
|
|
146
|
+
//# sourceMappingURL=override-floors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"override-floors.d.ts","sourceRoot":"","sources":["../../src/core/override-floors.ts"],"names":[],"mappings":"AAgCA,2EAA2E;AAC3E,eAAO,MAAM,0BAA0B,0FAK7B,CAAC;AAEX,oEAAoE;AACpE,eAAO,MAAM,iBAAiB,uCAAwC,CAAC;AAEvE,4CAA4C;AAC5C,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,YAAY,GAAG,UAAU,CAAC;AAEtE,2EAA2E;AAC3E,MAAM,WAAW,0BAA0B;IACzC,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,oBAAoB;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,wDAAwD;IACxD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,kCAAkC;IAClC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;IACxD;;;OAGG;IACH,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9C;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,6DAA6D;IAC7D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,oCAAoC;IACpC,QAAQ,CAAC,SAAS,EAAE,SAAS,0BAA0B,EAAE,CAAC;IAC1D,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,SAAS,sBAAsB,EAAE,CAAC;CACxD;AAED,2DAA2D;AAC3D,MAAM,WAAW,sBAAsB;IACrC,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,oBAAoB;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,wDAAwD;IACxD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKhE;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,GAAG,CAAC,MAAM,CAAC,CAMb;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAQ7B;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,EAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,GACb,OAAO,CAOT;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,oBAAoB,CAKtB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,GACjB,MAAM,GAAG,IAAI,CAUf;AAeD;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,kBAAkB,CA4CpB;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,0BAA0B,GACnC,MAAM,CAcR"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Shared vocabulary for npm `$name` override self-references and the
|
|
3
|
+
* security floors they can silently resolve downwards.
|
|
4
|
+
* @description
|
|
5
|
+
* An `overrides`/`resolutions` entry written `"$name"` means "whatever the
|
|
6
|
+
* direct dependency says". Lisa's templates force floors into those same two
|
|
7
|
+
* sections, so when a floored package is ALSO a direct dependency, the apply
|
|
8
|
+
* normalizes the forced literal to `$name` — and if the host's direct range
|
|
9
|
+
* starts below the floor, that rewrite would readmit exactly the versions the
|
|
10
|
+
* floor exists to exclude. `lisa apply` refuses rather than perform it.
|
|
11
|
+
*
|
|
12
|
+
* The refusal is correct. What it was missing is a way to be seen coming, and a
|
|
13
|
+
* remedy the operator can actually follow. Both halves are here, in ONE place,
|
|
14
|
+
* because they must agree by construction:
|
|
15
|
+
*
|
|
16
|
+
* - {@link classifySelfReferenceRewrite} is the single predicate. The apply's
|
|
17
|
+
* guard and `lisa doctor` both call it, so doctor can never report clean on a
|
|
18
|
+
* manifest the apply is about to refuse, nor cry wolf on one it accepts.
|
|
19
|
+
* - {@link suggestSatisfyingDirectRange} runs its own suggestion back through
|
|
20
|
+
* that same predicate before returning it. Advice that has not been tested
|
|
21
|
+
* against the guard is how CodySwannGT/lisa#3191 happened — an operator who
|
|
22
|
+
* did what the refusal told them was refused a second time, which reads as
|
|
23
|
+
* the guard being broken rather than the range being wrong. A suggestion that
|
|
24
|
+
* does not verify is withheld, not printed hopefully.
|
|
25
|
+
*
|
|
26
|
+
* Nothing here rewrites a host range or lowers a floor. Raising a dependency is
|
|
27
|
+
* a version decision with its own blast radius; this module names the raise and
|
|
28
|
+
* the operator makes it.
|
|
29
|
+
* @module core/override-floors
|
|
30
|
+
*/
|
|
31
|
+
import semver from "semver";
|
|
32
|
+
/** package.json sections whose keys are treated as direct dependencies. */
|
|
33
|
+
export const DIRECT_DEPENDENCY_SECTIONS = [
|
|
34
|
+
"dependencies",
|
|
35
|
+
"devDependencies",
|
|
36
|
+
"optionalDependencies",
|
|
37
|
+
"peerDependencies",
|
|
38
|
+
];
|
|
39
|
+
/** package.json sections that carry npm-style version overrides. */
|
|
40
|
+
export const OVERRIDE_SECTIONS = ["overrides", "resolutions"];
|
|
41
|
+
/**
|
|
42
|
+
* Narrow an unknown value to a plain object record, returning {} otherwise.
|
|
43
|
+
* @param value - Candidate value
|
|
44
|
+
* @returns The value as a record, or an empty record when it is not a plain object
|
|
45
|
+
*/
|
|
46
|
+
export function asRecord(value) {
|
|
47
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
return {};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Collect the names of every direct dependency declared across a package.json's
|
|
54
|
+
* dependency sections.
|
|
55
|
+
* @param pkg - Merged package.json object
|
|
56
|
+
* @returns Set of direct dependency names
|
|
57
|
+
*/
|
|
58
|
+
export function collectDirectDependencyNames(pkg) {
|
|
59
|
+
return new Set(DIRECT_DEPENDENCY_SECTIONS.flatMap(section => Object.keys(asRecord(pkg[section]))));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Collect direct dependency ranges by package name.
|
|
63
|
+
* @param pkg - Merged package.json object
|
|
64
|
+
* @returns Package name to string range map
|
|
65
|
+
*/
|
|
66
|
+
export function collectDirectDependencyRanges(pkg) {
|
|
67
|
+
return new Map(DIRECT_DEPENDENCY_SECTIONS.flatMap(section => Object.entries(asRecord(pkg[section])).flatMap(([name, value]) => typeof value === "string" ? [[name, value]] : [])));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Decide whether an override/resolution entry is a candidate for npm `$name`
|
|
71
|
+
* normalization at all.
|
|
72
|
+
* @param directDeps - Direct dependency names in the merged package
|
|
73
|
+
* @param name - Override/resolution key
|
|
74
|
+
* @param value - Override/resolution value
|
|
75
|
+
* @returns True when the entry is a literal direct-dependency collision
|
|
76
|
+
*/
|
|
77
|
+
export function needsSelfReferenceRewrite(directDeps, name, value) {
|
|
78
|
+
return (directDeps.has(name) &&
|
|
79
|
+
typeof value === "string" &&
|
|
80
|
+
value.length > 0 &&
|
|
81
|
+
!value.startsWith("$"));
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The one predicate behind both the apply's refusal and doctor's report.
|
|
85
|
+
* @remarks
|
|
86
|
+
* Deliberately plain `semver.subset`, with no ceiling normalization. The
|
|
87
|
+
* normalizing variant used by the host-pin branch (`rangeContains` in the
|
|
88
|
+
* package-lisa strategy) can only turn a refusal into an acceptance, and this
|
|
89
|
+
* branch is the one that decides whether a security floor may be resolved
|
|
90
|
+
* DOWNWARDS — so it keeps the stricter reading. Any range that reaches a
|
|
91
|
+
* `widening` verdict here still has a followable way out, because
|
|
92
|
+
* {@link suggestSatisfyingDirectRange} is verified against this same function.
|
|
93
|
+
* @param floorRange - The literal override range being replaced
|
|
94
|
+
* @param directRange - The direct dependency range `$name` would resolve to
|
|
95
|
+
* @returns Whether the rewrite is safe, unprovable, or widening
|
|
96
|
+
*/
|
|
97
|
+
export function classifySelfReferenceRewrite(floorRange, directRange) {
|
|
98
|
+
if (!semver.validRange(floorRange) || !semver.validRange(directRange)) {
|
|
99
|
+
return "unprovable";
|
|
100
|
+
}
|
|
101
|
+
return semver.subset(directRange, floorRange) ? "safe" : "widening";
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Derive a direct dependency range that satisfies the floor, and PROVE it does
|
|
105
|
+
* before handing it to an operator.
|
|
106
|
+
* @remarks
|
|
107
|
+
* The natural suggestion is a caret at the floor's minimum version, because
|
|
108
|
+
* that is what a person writes and what the one already-fixed instance of this
|
|
109
|
+
* defect was fixed with. It is not always right: measured, `^1.18.0` is not a
|
|
110
|
+
* subset of a bounded floor `>=1.18.0 <1.19.0`, and `^0.0.0` is not a subset of
|
|
111
|
+
* `*`. So the caret is a CANDIDATE, tested against
|
|
112
|
+
* {@link classifySelfReferenceRewrite} and discarded when it fails, falling
|
|
113
|
+
* back to the floor range verbatim — which is a subset of itself for any range
|
|
114
|
+
* semver can parse.
|
|
115
|
+
*
|
|
116
|
+
* A floor semver cannot parse yields null. Printing an untested range would be
|
|
117
|
+
* the #3191 failure exactly: advice that sends the operator back into the same
|
|
118
|
+
* refusal.
|
|
119
|
+
* @param floorRange - The literal override range acting as the floor
|
|
120
|
+
* @returns A range verified to satisfy the guard, or null when none exists
|
|
121
|
+
*/
|
|
122
|
+
export function suggestSatisfyingDirectRange(floorRange) {
|
|
123
|
+
const minimum = rangeMinimum(floorRange);
|
|
124
|
+
const candidates = minimum === null ? [floorRange] : [`^${minimum}`, floorRange];
|
|
125
|
+
return (candidates.find(candidate => classifySelfReferenceRewrite(floorRange, candidate) === "safe") ?? null);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Lowest version a range admits, without throwing on an unparseable range.
|
|
129
|
+
* @param range - An npm version range
|
|
130
|
+
* @returns The minimum version, or null when the range is not comparable
|
|
131
|
+
*/
|
|
132
|
+
function rangeMinimum(range) {
|
|
133
|
+
try {
|
|
134
|
+
return semver.minVersion(range)?.version ?? null;
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Judge every `$name`-rewrite candidate in a merged manifest, collecting ALL
|
|
142
|
+
* conflicts rather than stopping at the first.
|
|
143
|
+
* @remarks
|
|
144
|
+
* The apply throws on the first conflict, which is right for an apply — it is
|
|
145
|
+
* about to write a file and must not. A report has the opposite obligation: an
|
|
146
|
+
* operator who fixes the one package named and re-runs, only to be handed the
|
|
147
|
+
* next one, is being drip-fed a list Lisa already had in full.
|
|
148
|
+
* @param pkg - Merged package.json, as the apply would persist it
|
|
149
|
+
* @returns What was inspected and every conflict found
|
|
150
|
+
*/
|
|
151
|
+
export function auditSelfReferenceRewrites(pkg) {
|
|
152
|
+
const directDeps = collectDirectDependencyNames(pkg);
|
|
153
|
+
const directRanges = collectDirectDependencyRanges(pkg);
|
|
154
|
+
const entries = OVERRIDE_SECTIONS.flatMap(section => Object.entries(asRecord(pkg[section])).map(([name, value]) => [section, name, value]));
|
|
155
|
+
const judged = entries.flatMap(([section, name, value]) => {
|
|
156
|
+
if (!needsSelfReferenceRewrite(directDeps, name, value)) {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
const directRange = directRanges.get(name);
|
|
160
|
+
return directRange === undefined
|
|
161
|
+
? []
|
|
162
|
+
: [{ section, name, floorRange: value, directRange }];
|
|
163
|
+
});
|
|
164
|
+
const verdicts = judged.map(candidate => ({
|
|
165
|
+
candidate,
|
|
166
|
+
verdict: classifySelfReferenceRewrite(candidate.floorRange, candidate.directRange),
|
|
167
|
+
}));
|
|
168
|
+
return {
|
|
169
|
+
overridesInspected: entries.length,
|
|
170
|
+
rewritesJudged: judged.length,
|
|
171
|
+
conflicts: verdicts.flatMap(({ candidate, verdict }) => verdict === "safe"
|
|
172
|
+
? []
|
|
173
|
+
: [
|
|
174
|
+
{
|
|
175
|
+
...candidate,
|
|
176
|
+
verdict,
|
|
177
|
+
suggestedDirectRange: suggestSatisfyingDirectRange(candidate.floorRange),
|
|
178
|
+
},
|
|
179
|
+
]),
|
|
180
|
+
rewritable: verdicts.flatMap(({ candidate, verdict }) => verdict === "safe" ? [candidate] : []),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* The remedy sentence, shared by the apply's refusal and doctor's report so an
|
|
185
|
+
* operator is never told two different things about the same conflict.
|
|
186
|
+
* @param conflict - The conflict to describe
|
|
187
|
+
* @returns One operator-readable sentence naming the exact raise to make
|
|
188
|
+
*/
|
|
189
|
+
export function describeSelfReferenceRemedy(conflict) {
|
|
190
|
+
if (conflict.suggestedDirectRange === null) {
|
|
191
|
+
return (`Lisa could not derive a direct range that satisfies the floor ` +
|
|
192
|
+
`${JSON.stringify(conflict.floorRange)}, so it is not guessing one. ` +
|
|
193
|
+
`Reconcile ${conflict.name} by hand, or raise Lisa's template pin.`);
|
|
194
|
+
}
|
|
195
|
+
return (`Raise the direct dependency ${conflict.name} from ` +
|
|
196
|
+
`${JSON.stringify(conflict.directRange)} to ` +
|
|
197
|
+
`${JSON.stringify(conflict.suggestedDirectRange)}, which Lisa has ` +
|
|
198
|
+
`verified satisfies the floor ${JSON.stringify(conflict.floorRange)}.`);
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=override-floors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"override-floors.js","sourceRoot":"","sources":["../../src/core/override-floors.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,CAo6EpE,CAAC;AAEL,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,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,CAo6EpE,CAAC;AAEL,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CA6sPjE,CAAC;AAEL,sFAAsF;AACtF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAk6I/D,CAAC"}
|
|
@@ -21,7 +21,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
|
|
|
21
21
|
"all/copy-overwrite/scripts/lisa-hooks/block-managed-file-edits.sh": "d3ef2562b718156912f0877f8a0668026f5966fcca43eb9e064aa57a4e9a4976",
|
|
22
22
|
"all/copy-overwrite/scripts/lisa-hooks/block-no-verify.sh": "cdf59a4423ced0c1744a9742cd20a3e59eb728972be0657acde7c4658528fbfc",
|
|
23
23
|
"all/copy-overwrite/scripts/lisa-hooks/block-shell-json-parsing.sh": "234cb82cc9033bd04940a553d4ddc95b078e585e41777d6529d887676edc40b1",
|
|
24
|
-
"all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh": "
|
|
24
|
+
"all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh": "a211f1a06aecddb841851463da302f694ab0eafff6bab75ee944b0a58aac431d",
|
|
25
25
|
"all/copy-overwrite/scripts/lisa-hooks/sonar-secrets.sh": "f21cdcb54b353714a92c2d1e25fd6b76318e8e8d7cb90cdb016f174923c532ef",
|
|
26
26
|
"all/copy-overwrite/scripts/lisa-lint-staged-preflight.mjs": "ce4bc224a102e3ac2bc29d8f2038eefd619129d4639c25954c93f05011f7f977",
|
|
27
27
|
"all/copy-overwrite/scripts/lisa-postinstall.mjs": "d22fe47acf9a68828ca28b19b88e269bf535e77bc38952dec9f7a703269f1c44",
|
|
@@ -365,7 +365,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
|
|
|
365
365
|
"plugins/src/base/hooks/install-pkgs.sh": "e9a13faba849a277410dde911ab102ee6f88ef915b33571bb1d4eef904172db5",
|
|
366
366
|
"plugins/src/base/hooks/parity-safety-net-heredoc.py": "f21b1232ac82bd0e42d2ba43c68f4cc4546334fc885ba31747881f427097ef78",
|
|
367
367
|
"plugins/src/base/hooks/parity-safety-net.agy.sh": "ce9bd2b4566ad9147e4ace56434cffbbe87edb4ccbb57549ab3fd9f4c671ced4",
|
|
368
|
-
"plugins/src/base/hooks/parity-safety-net.sh": "
|
|
368
|
+
"plugins/src/base/hooks/parity-safety-net.sh": "c0b820f7b9a1992f11e8ac79b717a228bb3abb055dc72a8f2b11a489c7a6b68b",
|
|
369
369
|
"plugins/src/base/hooks/secrets-preflight.sh": "cdc638627e5769770aefb061ea0ddfacc1888a8eab3a5fade6c43129a2d3ff6e",
|
|
370
370
|
"plugins/src/base/hooks/setup-jira-cli.sh": "384bc8d935a2ed5788d7185979b3e74c75c17cd4bc5c230d7d8f086ab2703443",
|
|
371
371
|
"plugins/src/base/hooks/shell-write-nudge.sh": "69839af423f8792b1e52c71097316c3264425553031627c0a2f9409a9d5becd0",
|
|
@@ -7197,6 +7197,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
7197
7197
|
"src/cli/doctor-lisa-owned-universal.ts": true,
|
|
7198
7198
|
"src/cli/doctor-merge-drivers.ts": true,
|
|
7199
7199
|
"src/cli/doctor-monitor-thresholds.ts": true,
|
|
7200
|
+
"src/cli/doctor-override-floor-conflicts.ts": true,
|
|
7200
7201
|
"src/cli/doctor-readiness-action-pins.ts": true,
|
|
7201
7202
|
"src/cli/doctor-readiness-audit-allowlist.ts": true,
|
|
7202
7203
|
"src/cli/doctor-readiness-blockers.ts": true,
|
|
@@ -7442,6 +7443,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
7442
7443
|
"src/core/lisa-skill-sources.ts": true,
|
|
7443
7444
|
"src/core/lisa.ts": true,
|
|
7444
7445
|
"src/core/merge-driver-registration.ts": true,
|
|
7446
|
+
"src/core/override-floors.ts": true,
|
|
7445
7447
|
"src/core/project-config-kane.ts": true,
|
|
7446
7448
|
"src/core/project-config.ts": true,
|
|
7447
7449
|
"src/core/self-apply.ts": true,
|
|
@@ -7851,6 +7853,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
7851
7853
|
"tests/unit/cli/doctor-lisa-owned-artifacts.test.ts": true,
|
|
7852
7854
|
"tests/unit/cli/doctor-merge-drivers.test.ts": true,
|
|
7853
7855
|
"tests/unit/cli/doctor-monitor-thresholds.test.ts": true,
|
|
7856
|
+
"tests/unit/cli/doctor-override-floor-conflicts.test.ts": true,
|
|
7854
7857
|
"tests/unit/cli/doctor-readiness-blockers.test.ts": true,
|
|
7855
7858
|
"tests/unit/cli/doctor-readiness-capabilities.test.ts": true,
|
|
7856
7859
|
"tests/unit/cli/doctor-readiness-concurrent-write.test.ts": true,
|
|
@@ -8124,6 +8127,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
8124
8127
|
"tests/unit/core/lisa-plugin-selection.test.ts": true,
|
|
8125
8128
|
"tests/unit/core/lisa-skill-sources.test.ts": true,
|
|
8126
8129
|
"tests/unit/core/no-downstream-project-names.test.ts": true,
|
|
8130
|
+
"tests/unit/core/override-floors.test.ts": true,
|
|
8127
8131
|
"tests/unit/core/plugin-sync-marker.test.ts": true,
|
|
8128
8132
|
"tests/unit/core/project-config-harness-migration.test.ts": true,
|
|
8129
8133
|
"tests/unit/core/project-config-kane.test.ts": true,
|
|
@@ -8213,6 +8217,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
8213
8217
|
"tests/unit/hooks/parity-safety-net-heredoc-literal.test.ts": true,
|
|
8214
8218
|
"tests/unit/hooks/parity-safety-net-heredoc.test.ts": true,
|
|
8215
8219
|
"tests/unit/hooks/parity-safety-net-line-continuation.test.ts": true,
|
|
8220
|
+
"tests/unit/hooks/parity-safety-net-prose-remedy.test.ts": true,
|
|
8216
8221
|
"tests/unit/hooks/parity-safety-net-scan-failure.test.ts": true,
|
|
8217
8222
|
"tests/unit/hooks/parity-safety-net.test.ts": true,
|
|
8218
8223
|
"tests/unit/hooks/post-checkout.test.ts": true,
|
|
@@ -8670,6 +8675,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
8670
8675
|
"tests/unit/strategies/multi-repo-container-decomposition.test.ts": true,
|
|
8671
8676
|
"tests/unit/strategies/not-established-section-contract.test.ts": true,
|
|
8672
8677
|
"tests/unit/strategies/package-lisa-integration-script-layout.test.ts": true,
|
|
8678
|
+
"tests/unit/strategies/package-lisa-override-floor-remedy.test.ts": true,
|
|
8673
8679
|
"tests/unit/strategies/package-lisa-script-composition.test.ts": true,
|
|
8674
8680
|
"tests/unit/strategies/package-lisa-script-report.test.ts": true,
|
|
8675
8681
|
"tests/unit/strategies/package-lisa-version-pin.test.ts": true,
|