redlinegate 0.0.2 → 0.0.3

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 (63) hide show
  1. package/README.md +2 -2
  2. package/dist/bin/redline.js +247 -42
  3. package/dist/bin/redline.js.map +1 -1
  4. package/dist/commands/init.js +274 -26
  5. package/dist/commands/init.js.map +1 -1
  6. package/dist/commands/remove.js +40 -0
  7. package/dist/commands/remove.js.map +1 -1
  8. package/dist/commands/status.js +94 -0
  9. package/dist/commands/status.js.map +1 -0
  10. package/dist/config/redline-json.js +18 -1
  11. package/dist/config/redline-json.js.map +1 -1
  12. package/dist/core/git.js +50 -3
  13. package/dist/core/git.js.map +1 -1
  14. package/dist/core/version.js +6 -0
  15. package/dist/core/version.js.map +1 -1
  16. package/dist/detect/setup.js +200 -0
  17. package/dist/detect/setup.js.map +1 -0
  18. package/dist/detect/stack.js +56 -17
  19. package/dist/detect/stack.js.map +1 -1
  20. package/dist/metrics/options.js +0 -9
  21. package/dist/metrics/options.js.map +1 -1
  22. package/dist/platforms/azure/install.js +1 -5
  23. package/dist/platforms/azure/install.js.map +1 -1
  24. package/dist/platforms/azure/verify.js +4 -2
  25. package/dist/platforms/azure/verify.js.map +1 -1
  26. package/dist/platforms/github/install.js +110 -22
  27. package/dist/platforms/github/install.js.map +1 -1
  28. package/dist/platforms/github/vendor.js +81 -0
  29. package/dist/platforms/github/vendor.js.map +1 -0
  30. package/dist/platforms/github/verify.js +17 -2
  31. package/dist/platforms/github/verify.js.map +1 -1
  32. package/dist/platforms/types.js +4 -0
  33. package/dist/platforms/types.js.map +1 -1
  34. package/dist/render/standards.js +8 -1
  35. package/dist/render/standards.js.map +1 -1
  36. package/dist/render/vendors.js +9 -52
  37. package/dist/render/vendors.js.map +1 -1
  38. package/dist/rules/catalogue.js +127 -0
  39. package/dist/rules/catalogue.js.map +1 -0
  40. package/dist/ui/facts.js +30 -1
  41. package/dist/ui/facts.js.map +1 -1
  42. package/dist/ui/prompt.js +137 -8
  43. package/dist/ui/prompt.js.map +1 -1
  44. package/dist/ui/report.js +214 -0
  45. package/dist/ui/report.js.map +1 -0
  46. package/dist/ui/tty.js +358 -25
  47. package/dist/ui/tty.js.map +1 -1
  48. package/dist/ui/wizard.js +133 -19
  49. package/dist/ui/wizard.js.map +1 -1
  50. package/dist/verify/remote.js +33 -0
  51. package/dist/verify/remote.js.map +1 -1
  52. package/package.json +4 -1
  53. package/scripts/fetch-stars.mjs +92 -0
  54. package/scripts/lib/rules.d.mts +18 -0
  55. package/scripts/publish-local.mjs +183 -0
  56. package/standards/manifest.json +79 -8
  57. package/standards/stacks/angular.md +57 -0
  58. package/standards/stacks/dom.md +61 -0
  59. package/standards/stacks/svelte.md +45 -0
  60. package/standards/stacks/vue.md +54 -0
  61. package/templates/redline.yml +4 -0
  62. package/workflows/redline-gate.yml +28 -4
  63. package/scripts/measure-context.mjs +0 -101
package/dist/ui/wizard.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { RedlineError } from "../core/errors.js";
2
+ import { TOOL_PROBES } from "../detect/existing.js";
1
3
  import { RUNGS } from "../enforce/ladder.js";
2
4
  // Plain-English, at the moment of choosing. Every one of these was a term the
3
5
  // operator met for the first time in output that assumed they knew it.
@@ -21,14 +23,20 @@ const STAND_DOWN_LABEL = {
21
23
  dependencies: 'dependency vulnerability review',
22
24
  policy: 'static analysis',
23
25
  };
24
- function profileChoices(manifest, detected) {
25
- const ids = Object.keys(manifest.profiles).sort((a, b) => {
26
- if (a === detected)
27
- return -1;
28
- if (b === detected)
29
- return 1;
30
- return a.localeCompare(b);
31
- });
26
+ /**
27
+ * The profile list, ordered by how much detection actually knows.
28
+ *
29
+ * A confident detection — the repository's own manifest naming its framework —
30
+ * is hoisted to the top and marked, because it is almost always the answer. A
31
+ * guess is not: hoisting it puts it on the first row with the cursor already on
32
+ * it, which reads as chosen no matter how carefully it is left unticked. So a
33
+ * guess sorts alphabetically with everything else and says what it is.
34
+ */
35
+ function profileChoices(manifest, detected, confidence) {
36
+ // Alphabetical, always. Hoisting the detected profile to the first row put the
37
+ // cursor on it before anything was typed, which reads as chosen no matter how
38
+ // carefully it is left unticked.
39
+ const ids = Object.keys(manifest.profiles).sort((a, b) => a.localeCompare(b));
32
40
  return ids.map((id) => {
33
41
  // The stacks' own titles, not their ids. `JavaScript, React (web)` tells an
34
42
  // operator what they are choosing; `javascript, react` makes them guess at
@@ -37,7 +45,12 @@ function profileChoices(manifest, detected) {
37
45
  return {
38
46
  value: id,
39
47
  label: id,
40
- hint: stacks.join(', ') + (id === detected ? ' (detected)' : ''),
48
+ hint: stacks.join(', ') +
49
+ (id === detected
50
+ ? confidence === 'high'
51
+ ? ' — looks like this repository, but pick it yourself'
52
+ : ' — a guess; nothing here names this framework'
53
+ : ''),
41
54
  };
42
55
  });
43
56
  }
@@ -72,6 +85,7 @@ function vendorChoices(manifest) {
72
85
  */
73
86
  export async function runWizard(p, facts) {
74
87
  const { manifest, survey, recorded } = facts;
88
+ const defaultOwner = facts.defaultOwner ?? 'the platform team';
75
89
  p.intro('Redline');
76
90
  // Multi-select, because a repository is routinely more than one bundle: a
77
91
  // React application with its own Terraform beside it is `web,infra`, and a
@@ -79,13 +93,33 @@ export async function runWizard(p, facts) {
79
93
  //
80
94
  // `.redline.json` still records one string — resolveProfile takes the list
81
95
  // and sorts it — so nothing downstream had to learn a new shape.
96
+ // Detection never ticks a row. Which standards a repository is held to is the
97
+ // one answer here that changes what every future pull request is judged
98
+ // against, and a ticked row is consent — an operator pressing enter through
99
+ // the menu has agreed to whatever was ticked, whether or not they read it.
100
+ // Detection earns a label on the row and nothing more.
101
+ //
102
+ // What the repository already recorded is different: that is a decision a
103
+ // person made here before, and re-asking for it from scratch on every run
104
+ // would be its own kind of rude.
82
105
  const recordedProfiles = recorded?.profile?.split(',').map((s) => s.trim());
83
- const profiles = await p.multiselect('Which standards apply here?', profileChoices(manifest, facts.detectedProfile), recordedProfiles ?? [facts.detectedProfile]);
84
- // Deselecting everything renders no rules at all, which is never what the
85
- // operator meant by "none of these" they meant they could not find theirs.
86
- // Falling back to what was detected keeps the run useful and keeps the answer
87
- // visible in the summary, where it can be changed.
88
- const profile = profiles.length > 0 ? profiles.join(',') : facts.detectedProfile;
106
+ let profiles = await p.multiselect('Which standards apply here?', profileChoices(manifest, facts.detectedProfile, facts.detectedConfidence), recordedProfiles ?? []);
107
+ // And if nothing is chosen, ask once more rather than choose something.
108
+ // Falling back to the detected profile is how "I did not pick anything"
109
+ // quietly became "Redline picked for me", which is the whole complaint.
110
+ //
111
+ // Once, not until-they-comply: a loop here never ends against a caller that
112
+ // keeps answering nothing, and a prompt that cannot be escaped is worse than
113
+ // one that gives up and says how to pass the answer as a flag.
114
+ if (profiles.length === 0) {
115
+ p.note('Nothing selected — Redline needs at least one profile to know which rules apply here. ' +
116
+ `The checkout looks like ${facts.detectedProfile}; take that, or take another.`);
117
+ profiles = await p.multiselect('Which standards apply here?', profileChoices(manifest, facts.detectedProfile, facts.detectedConfidence), []);
118
+ }
119
+ if (profiles.length === 0) {
120
+ throw new RedlineError('usage', 'no profile chosen, so there are no rules to render', `pick one from the menu, or name it outright: redline init --profile ${facts.detectedProfile}`);
121
+ }
122
+ const profile = profiles.join(',');
89
123
  const hostChoices = [
90
124
  {
91
125
  value: 'github',
@@ -134,22 +168,93 @@ export async function runWizard(p, facts) {
134
168
  hint: 'resource naming, @type, paging, error bodies. Only if you implement TMF APIs',
135
169
  },
136
170
  ], ['speckit']);
171
+ // What Redline should set up, not what it noticed. A question whose only
172
+ // outcome was a sentence in the report earned nothing: the operator read a
173
+ // list of tools, ticked the ones they had, and nothing happened differently.
174
+ //
175
+ // Only controls Redline can install with no account and no token appear here,
176
+ // and only on a host where they mean something — on Azure DevOps the list is
177
+ // empty and the question does not get asked at all. What the repository
178
+ // already runs is still detected, and still stands Redline's own gate jobs
179
+ // down; it just does not need a question to do it.
180
+ const already = new Set(facts.recorded?.integrations?.length
181
+ ? facts.recorded.integrations
182
+ : survey.tools.map((tool) => tool.id));
183
+ const setupChoices = facts.offerable.map((offer) => ({
184
+ value: offer.id,
185
+ label: offer.label,
186
+ ...(already.has(offer.id)
187
+ ? { disabled: `already here — ${offer.evidence ?? 'detected in this repository'}` }
188
+ : { hint: offer.hint }),
189
+ }));
190
+ const setup = setupChoices.length > 0
191
+ ? await p.multiselect('What should Redline set up alongside its own checks?', setupChoices, [])
192
+ : [];
193
+ // The recorded list stays what the repository RUNS — detection plus anything
194
+ // stated with --integrations — and gains whatever was just installed, because
195
+ // after this run it does run it.
196
+ const integrations = [...new Set([...already, ...setup])];
137
197
  // A capability a detected tool already covers starts deselected and says
138
198
  // which tool. `standDown` is advisory: nothing here is decided for the
139
199
  // operator, only defaulted.
140
200
  const covered = new Map();
141
- for (const tool of survey.tools) {
142
- if (tool.standsDown === null)
201
+ for (const id of integrations) {
202
+ const probe = TOOL_PROBES.find((candidate) => candidate.id === id);
203
+ if (probe === undefined || probe.standsDown === null)
143
204
  continue;
144
- covered.set(tool.standsDown, tool.label);
205
+ covered.set(probe.standsDown, probe.label);
145
206
  }
146
207
  const capabilityChoices = Object.entries(CAPABILITY_HINTS).map(([id, hint]) => ({ value: id, label: id, hint }));
147
208
  const capabilities = await p.multiselect('What should Redline install?', capabilityChoices, ['gate', 'merge-policy', 'labels']);
209
+ // Asked here, and asked blind: the wizard runs before the platform is
210
+ // resolved, so nothing yet knows whether this organisation publishes a gate.
211
+ // That is why it defaults to `org` and why the mid-run offer still exists —
212
+ // this question is the operator's preference, and the later one is the same
213
+ // question asked once the host has actually answered. An operator who already
214
+ // knows their organisation has nothing can say so here and never see it.
215
+ const gateSource = capabilities.includes('gate')
216
+ ? await p.select('Where should the merge gate live?', [
217
+ {
218
+ value: 'org',
219
+ label: 'in the organisation',
220
+ hint: 'one shared workflow; a pull request cannot edit the gate that judges it',
221
+ },
222
+ {
223
+ value: 'local',
224
+ label: 'in this repository',
225
+ hint: 'no organisation setup needed — weaker: a PR can edit its own gate',
226
+ },
227
+ ], 'org')
228
+ : 'org';
229
+ // Asked only when the capability was taken. GitHub silently ignores an owner
230
+ // it cannot resolve, so a CODEOWNERS seeded with a team that does not exist
231
+ // reports as installed and enforces nothing — the one failure mode worth a
232
+ // question, and only for the operators who will actually get a file.
233
+ const reviewOwners = capabilities.includes('review-ownership')
234
+ ? (await p.text('Who owns the paths Redline protects?', {
235
+ placeholder: `${defaultOwner} — the default, which may not exist here`,
236
+ hint: 'a team, a user or an email; several separated by commas. GitHub ignores an owner it cannot resolve',
237
+ }))
238
+ .split(',')
239
+ .map((owner) => owner.trim())
240
+ .filter((owner) => owner !== '')
241
+ : [];
148
242
  if (covered.size > 0) {
149
243
  const named = [...covered]
150
244
  .map(([job, label]) => `${label} already covers ${STAND_DOWN_LABEL[job] ?? job}`)
151
245
  .join('; ');
152
- p.note(`${named}. Redline adds its own on top rather than replacing them.`);
246
+ p.note(`${named}. Those gate jobs are stood down rather than run a second time — ` +
247
+ 'the rest of the gate still runs.');
248
+ }
249
+ else {
250
+ // The other half of that question, and the half that was missing: what
251
+ // happens when the answer is "none of these". Redline turns on what the
252
+ // host itself provides, and is plain that it does not install anybody
253
+ // else's scanner — offering to would be a promise it cannot keep.
254
+ p.note('Nothing ticked — Redline will switch on the host controls itself: secret scanning, ' +
255
+ 'push protection and dependency alerts. It does not install third-party scanners ' +
256
+ '(SonarQube, Snyk, Mend). Add one when you want it, then re-run ' +
257
+ '`redline init --integrations <id>` and the gate stops duplicating what it covers.');
153
258
  }
154
259
  const rung = await p.select('How hard should the check bite?', RUNGS.map((value) => ({ value, label: value, hint: RUNG_HINTS[value] })), recorded?.rung ?? 'observe');
155
260
  const action = await p.select('Ready?', [
@@ -158,6 +263,11 @@ export async function runWizard(p, facts) {
158
263
  label: 'Dry run',
159
264
  hint: 'print the plan — writes nothing, contacts no host, needs no credential',
160
265
  },
266
+ {
267
+ value: 'no-commit',
268
+ label: 'Write the files only',
269
+ hint: 'writes into your working tree, uncommitted — no host changes, no pull request',
270
+ },
161
271
  {
162
272
  value: 'apply',
163
273
  label: 'Apply',
@@ -172,7 +282,11 @@ export async function runWizard(p, facts) {
172
282
  speckit: contexts.includes('speckit'),
173
283
  tmf: contexts.includes('tmf'),
174
284
  capabilities,
285
+ integrations,
286
+ setup,
287
+ reviewOwners,
175
288
  rung,
289
+ gateSource,
176
290
  action,
177
291
  };
178
292
  }
@@ -1 +1 @@
1
- {"version":3,"file":"wizard.js","sourceRoot":"","sources":["../../cli/ui/wizard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wizard.js","sourceRoot":"","sources":["../../cli/ui/wizard.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  import { isRedlineError } from "../core/errors.js";
2
2
  import { renderForTarget, managedPaths } from "../sync/render.js";
3
3
  export const CALLER_WORKFLOW = '.github/workflows/redline.yml';
4
+ import { VENDORED_GATE_PATH, stampedVersion } from "../platforms/github/vendor.js";
5
+ export { VENDORED_GATE_PATH } from "../platforms/github/vendor.js";
4
6
  // Verify a repository without a checkout.
5
7
  //
6
8
  // Every check that can be sourced from the host is, and every check that cannot
@@ -70,6 +72,37 @@ export async function verifyRemote(host, ref, opts) {
70
72
  : machinery.publishes !== machinery.expected
71
73
  ? `${machinery.path} publishes ${machinery.publishes}, but the policy requires ${machinery.expected}`
72
74
  : `publishes ${machinery.publishes}`);
75
+ // --- vendored gate ---------------------------------------------------------
76
+ // A gate referenced from the organisation updates itself: one merge there
77
+ // reaches every repository that points at it. A vendored one does not — it is
78
+ // a copy, and a copy is only as current as the run that wrote it. Nothing
79
+ // else in this report would notice a repository sitting three releases behind
80
+ // on the workflow that decides whether its pull requests can merge.
81
+ //
82
+ // Reported against the CLI running the check rather than against npm: this is
83
+ // the same comparison `redline init --repair` would act on, so a repository
84
+ // told it is behind can always be brought level by the binary that told it.
85
+ if (gateOwned && config.gateSource === 'local') {
86
+ const vendored = await host.readRemoteFile(ref, VENDORED_GATE_PATH);
87
+ const pin = vendored === null ? null : stampedVersion(vendored.content);
88
+ if (vendored === null) {
89
+ add('gate-vendored', false, `${VENDORED_GATE_PATH} is missing, but .redline.json says the gate is vendored here — ` +
90
+ 'the caller workflow references a file that is not in this repository');
91
+ }
92
+ else if (pin === null || config.gateVersion === '') {
93
+ // One of the two sides has no version to compare. That is not drift, and
94
+ // reporting it as stale would file work against a repository whose gate
95
+ // may be perfectly current — a development build writes no stamp on
96
+ // purpose. Unknown, with the reason, is the honest answer.
97
+ add('gate-vendored', true, 'vendored, version not recorded — cannot tell current from stale here', true);
98
+ }
99
+ else {
100
+ add('gate-vendored', pin === opts.cliVersion, pin === opts.cliVersion
101
+ ? `vendored, current with redlinegate ${pin}`
102
+ : `vendored at redlinegate ${pin}, but this check runs ${opts.cliVersion} — ` +
103
+ 're-run redline init --repair in that repository to bring the gate level');
104
+ }
105
+ }
73
106
  // --- merge policy ----------------------------------------------------------
74
107
  const policy = await host.readPolicy(ref);
75
108
  if (!config.capabilities.mergePolicy) {
@@ -1 +1 @@
1
- {"version":3,"file":"remote.js","sourceRoot":"","sources":["../../cli/verify/remote.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"remote.js","sourceRoot":"","sources":["../../cli/verify/remote.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "redlinegate",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Engineering control plane for AI-assisted development: standards, merge gates and evidence across GitHub and Azure DevOps",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -50,6 +50,9 @@
50
50
  "scripts": {
51
51
  "build": "rm -rf dist && tsc -p tsconfig.build.json",
52
52
  "prepack": "npm run build",
53
+ "stars": "node scripts/fetch-stars.mjs",
54
+ "publish:local": "node scripts/publish-local.mjs",
55
+ "publish:local:clean": "npm rm -g redlinegate",
53
56
  "test": "node --test 'cli/**/__tests__/*.test.ts' 'scripts/**/__tests__/*.test.mjs'",
54
57
  "typecheck": "tsc --noEmit"
55
58
  },
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Refreshes web/lib/github-stars.json.
4
+ *
5
+ * Star counts drift. Rather than pretend otherwise we snapshot them, record the
6
+ * date the snapshot was taken, and render that date next to the number. The
7
+ * build never calls the network: if this file is stale, the site says so; if a
8
+ * repo is missing from it, the site omits the count for that repo rather than
9
+ * guessing.
10
+ *
11
+ * Run: node scripts/fetch-stars.mjs (needs an authenticated `gh`)
12
+ */
13
+ import { execFile } from "node:child_process";
14
+ import { readFile, writeFile } from "node:fs/promises";
15
+ import { promisify } from "node:util";
16
+
17
+ const run = promisify(execFile);
18
+
19
+ const SOURCE = new URL("../web/lib/skills-catalog.ts", import.meta.url);
20
+ const OUT = new URL("../web/lib/github-stars.json", import.meta.url);
21
+
22
+ /** Pull every `owner`/`repo` pair out of the PUBLISHERS table. */
23
+ function repoSlugs(src) {
24
+ const re = /owner:\s*"([^"]+)",\s*\n\s*repo:\s*"([^"]+)"/g;
25
+ const slugs = new Set();
26
+ for (const m of src.matchAll(re)) slugs.add(`${m[1]}/${m[2]}`);
27
+ return [...slugs].sort();
28
+ }
29
+
30
+ async function stars(slug) {
31
+ // execFile, not exec: `slug` goes in as one argv entry, never through a shell.
32
+ const { stdout } = await run("gh", [
33
+ "api",
34
+ `repos/${slug}`,
35
+ "--jq",
36
+ ".stargazers_count",
37
+ ]);
38
+ const n = Number.parseInt(stdout.trim(), 10);
39
+ if (!Number.isFinite(n)) throw new Error(`unparseable count for ${slug}`);
40
+ return n;
41
+ }
42
+
43
+ const src = await readFile(SOURCE, "utf8");
44
+ const slugs = repoSlugs(src);
45
+ if (slugs.length === 0) {
46
+ console.error("No owner/repo pairs found — did PUBLISHERS move?");
47
+ process.exit(1);
48
+ }
49
+
50
+ const previous = await readFile(OUT, "utf8").then(
51
+ (t) => JSON.parse(t).stars ?? {},
52
+ () => ({}),
53
+ );
54
+
55
+ const next = {};
56
+ let failed = 0;
57
+ for (const slug of slugs) {
58
+ try {
59
+ next[slug] = await stars(slug);
60
+ console.log(` ${String(next[slug]).padStart(7)} ${slug}`);
61
+ } catch (err) {
62
+ failed += 1;
63
+ // Drop the repo rather than carry the previous run's number forward. Every
64
+ // value in this file is stamped with one shared fetchedAt, so a carried
65
+ // number would be published under a date on which nobody counted it —
66
+ // the exact misstatement the dated snapshot exists to prevent. A repo with
67
+ // no number simply renders without the stars fact, which is honest.
68
+ console.warn(` failed: ${slug} — ${err.message.split("\n")[0]}`);
69
+ }
70
+ }
71
+
72
+ if (failed === slugs.length) {
73
+ console.error("Every request failed; leaving the existing snapshot alone.");
74
+ process.exit(1);
75
+ }
76
+
77
+ const payload = {
78
+ fetchedAt: new Date().toISOString().slice(0, 10),
79
+ stars: Object.fromEntries(Object.entries(next).sort(([a], [b]) => a.localeCompare(b))),
80
+ };
81
+
82
+ const dropped = Object.keys(previous).filter((slug) => !(slug in next));
83
+ if (dropped.length) {
84
+ console.warn(
85
+ `\n${dropped.length} repo(s) in the previous snapshot have no number this run ` +
86
+ `and were dropped rather than re-dated: ${dropped.join(", ")}.\n` +
87
+ `Re-run to restore them; their pages render without a stars fact meanwhile.`,
88
+ );
89
+ }
90
+
91
+ await writeFile(OUT, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
92
+ console.log(`\nWrote ${Object.keys(payload.stars).length} repos to lib/github-stars.json`);
@@ -0,0 +1,18 @@
1
+ // Types for the CI rule parser, so cli/rules/__tests__/catalogue.test.ts can hold
2
+ // the CLI's own reader against it without an untyped import. The runtime module
3
+ // stays plain .mjs: it is run by node directly, never built.
4
+ export interface ScriptRule {
5
+ id: string;
6
+ stack: string;
7
+ severity: 'BLOCKER' | 'HIGH' | 'SUGGESTION';
8
+ text: string;
9
+ source: string;
10
+ line: number;
11
+ }
12
+
13
+ export declare const ROOT: string;
14
+ export declare const SEVERITIES: readonly string[];
15
+ export declare const RANK: Record<string, number>;
16
+ export declare const RULE_ID: RegExp;
17
+ export declare const RESERVED_RULE_IDS: ReadonlySet<string>;
18
+ export declare function loadRules(root?: string): Map<string, ScriptRule>;
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env node
2
+ // Build, pack and install this CLI globally, so `redline` on PATH is the working tree.
3
+ //
4
+ // The whole reason this is a script and not a one-line npm chain: which `npm` runs
5
+ // the global install decides whether the install is visible at all.
6
+ //
7
+ // Under pnpm, `npm` resolves to ./node_modules/.bin/npm — a locally installed npm
8
+ // that is not shimmed by Volta. Its `npm i -g` writes into its own global prefix,
9
+ // while the `redline` command on PATH is a Volta shim pointing at Volta's package
10
+ // image. The install reports success, the tarball is correct, and the binary you
11
+ // run is still the old one. That failure is silent and costs an hour.
12
+ //
13
+ // So: resolve npm explicitly, never through a node_modules/.bin that a package
14
+ // manager put in front, and verify afterwards that the binary on PATH is actually
15
+ // the build we just made.
16
+
17
+ import { execFileSync, execSync } from 'node:child_process';
18
+ import { createHash } from 'node:crypto';
19
+ import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
20
+ import { dirname, join, resolve } from 'node:path';
21
+ import { fileURLToPath } from 'node:url';
22
+
23
+ const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
24
+ // Present only in a current build: the check at the end greps the installed
25
+ // binary's own help for it.
26
+ const MARKER = 'redline status';
27
+
28
+ const run = (file, args, opts = {}) =>
29
+ execFileSync(file, args, { cwd: ROOT, stdio: 'inherit', ...opts });
30
+
31
+ // Volta sets _VOLTA_TOOL_RECURSION on anything it launches, and its shims skip
32
+ // their own hook when they see it — sensible, since it stops a tool Volta ran
33
+ // from re-entering Volta forever. It also means a global install performed from
34
+ // inside a script Volta started never updates the shim: the files land, npm says
35
+ // "added 1 package", and the `redline` on PATH keeps running the old build. That
36
+ // single variable is why every publish this session appeared to succeed and
37
+ // changed nothing. Clearing it for the install restores the behaviour of typing
38
+ // the command in a shell.
39
+ const withoutVoltaGuard = () => {
40
+ const env = { ...process.env };
41
+ delete env['_VOLTA_TOOL_RECURSION'];
42
+ return env;
43
+ };
44
+
45
+ const quiet = (command) => {
46
+ try {
47
+ return execSync(command, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
48
+ } catch {
49
+ return '';
50
+ }
51
+ };
52
+
53
+ /**
54
+ * The npm that a global install has to go through.
55
+ *
56
+ * Under Volta this is `~/.volta/bin/npm` — the SHIM. Not `volta which npm`,
57
+ * which returns the image binary underneath it: installing through that writes
58
+ * the package into the node image and never triggers the hook that builds the
59
+ * package image the `redline` shim actually executes. The install reports
60
+ * success, the files land, and the command keeps running the old build.
61
+ *
62
+ * Then any npm on PATH that is not inside a node_modules — that is one a package
63
+ * manager shadowed, as pnpm does with the npm semantic-release depends on.
64
+ */
65
+ function resolveNpm() {
66
+ const shim = join(process.env.HOME ?? '', '.volta', 'bin', 'npm');
67
+ if (existsSync(shim)) return shim;
68
+
69
+ for (const dir of (process.env.PATH ?? '').split(':')) {
70
+ if (dir === '' || dir.includes('node_modules')) continue;
71
+ const candidate = join(dir, 'npm');
72
+ if (existsSync(candidate)) return candidate;
73
+ }
74
+ return 'npm';
75
+ }
76
+
77
+ /**
78
+ * The `redline` a person actually gets when they type it.
79
+ *
80
+ * PATH first. Falling back to Volta's shim matters because a non-interactive
81
+ * shell does not always carry ~/.volta/bin, and reporting "not installed" to
82
+ * somebody whose terminal runs it perfectly well is worse than useless.
83
+ */
84
+ function liveBinary() {
85
+ // The shim first, when there is one. It is what a person's interactive shell
86
+ // runs, and it is the copy that goes stale — `command -v redline` in a
87
+ // non-interactive shell can easily resolve to a different, fresher copy and
88
+ // report success for a binary nobody types.
89
+ const shim = join(process.env.HOME ?? '', '.volta', 'bin', 'redline');
90
+ if (existsSync(shim)) return shim;
91
+ return quiet('command -v redline') !== '' ? 'redline' : '';
92
+ }
93
+
94
+ const npm = resolveNpm();
95
+ console.log(` using npm at ${npm}`);
96
+
97
+ // A unique version per publish, and this is the load-bearing part.
98
+ //
99
+ // package.json carries 0.0.0-development permanently — semantic-release sets the
100
+ // real version at publish time. Both npm and Volta key a global package by
101
+ // name@version, so every local publish looked identical to the last one and was
102
+ // served from cache: the tarball was rebuilt, the install reported success, and
103
+ // Volta restored the SAME old package image behind the shim. Each publish was
104
+ // actively downgrading the binary back to whatever was cached first.
105
+ //
106
+ // Stamping a timestamp version defeats both caches, and has a second use: the
107
+ // version `redline --version` prints is now the moment it was installed, so a
108
+ // stale binary is visible without any of this archaeology.
109
+ const manifestPath = join(ROOT, 'package.json');
110
+ const original = readFileSync(manifestPath, 'utf8');
111
+ const manifest = JSON.parse(original);
112
+ const localVersion = `0.0.0-local.${Math.floor(Date.now() / 1000)}`;
113
+ const tarball = `redlinegate-${localVersion}.tgz`;
114
+
115
+ // Clear Volta's entry first, and before anything else.
116
+ //
117
+ // Volta keeps its own copy of a global package — the one its shim runs — apart
118
+ // from the node image npm writes to. While it holds an entry, `npm i -g` updates
119
+ // only the node image and the shim keeps executing the old code. Order matters:
120
+ // clearing it after the pack leaves the shim deleted and not recreated, which is
121
+ // how `redline` kept vanishing from PATH.
122
+ const hasVolta = quiet('volta --version') !== '';
123
+ if (hasVolta) {
124
+ try {
125
+ execFileSync('volta', ['uninstall', 'redlinegate'], {
126
+ stdio: 'ignore',
127
+ env: withoutVoltaGuard(),
128
+ });
129
+ } catch {
130
+ // Not installed through Volta. Nothing to clear.
131
+ }
132
+ }
133
+
134
+ try {
135
+ writeFileSync(
136
+ manifestPath,
137
+ JSON.stringify({ ...manifest, version: localVersion }, null, 2) + '\n',
138
+ 'utf8'
139
+ );
140
+
141
+ run(npm, ['run', 'build']);
142
+ run(npm, ['pack']);
143
+
144
+ run(npm, ['i', '-g', `./${tarball}`], { env: withoutVoltaGuard() });
145
+ } finally {
146
+ // The real version is semantic-release's to set. Restoring it has to survive a
147
+ // failed build, or a crash here leaves a timestamp version committed.
148
+ writeFileSync(manifestPath, original, 'utf8');
149
+ rmSync(join(ROOT, tarball), { force: true });
150
+ }
151
+
152
+ // Verify by RUNNING both and comparing what they print.
153
+ //
154
+ // Every other way of checking this was wrong at least once. A marker string in
155
+ // --help stays true across builds, so it passed while the installed copy was
156
+ // three changes behind. Comparing files means guessing which of the copies the
157
+ // command resolves to — and under Volta there are two, in different places,
158
+ // only one of which the shim executes. Executing it answers the only question
159
+ // that matters: does the command a person types run the code just built.
160
+ const binary = liveBinary();
161
+ if (binary === '') {
162
+ console.error('\n redline is not on PATH after installing. Check your shell PATH.\n');
163
+ process.exit(1);
164
+ }
165
+
166
+ const live = quiet(`${binary} --help`);
167
+ const built = quiet(`node "${join(ROOT, 'dist', 'bin', 'redline.js')}" --help`);
168
+ const digest = (text) => createHash('sha256').update(text).digest('hex').slice(0, 12);
169
+
170
+ if (live === '' || built === '') {
171
+ console.error('\n Could not run redline to compare builds.\n');
172
+ process.exit(1);
173
+ }
174
+ if (live !== built) {
175
+ console.error('\n The installed redline is STALE: it runs older code than this build.');
176
+ console.error(` installed ${digest(live)} built ${digest(built)}`);
177
+ console.error('\n Under Volta the package image is cached by name@version, and this version');
178
+ console.error(' never changes. Clear it and install again:');
179
+ console.error(' volta uninstall redlinegate');
180
+ console.error(' ~/.volta/bin/npm i -g ./redlinegate-<version>.tgz\n');
181
+ process.exit(1);
182
+ }
183
+ console.log(` installed redline runs this build (${digest(built)})`);