redlinegate 0.0.1

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 (198) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +188 -0
  3. package/commands/redline-init.md +54 -0
  4. package/commands/redline-verify.md +69 -0
  5. package/dist/bin/redline.js +605 -0
  6. package/dist/bin/redline.js.map +1 -0
  7. package/dist/commands/exempt.js +45 -0
  8. package/dist/commands/exempt.js.map +1 -0
  9. package/dist/commands/init.js +615 -0
  10. package/dist/commands/init.js.map +1 -0
  11. package/dist/commands/policy.js +25 -0
  12. package/dist/commands/policy.js.map +1 -0
  13. package/dist/commands/remove.js +427 -0
  14. package/dist/commands/remove.js.map +1 -0
  15. package/dist/commands/review.js +72 -0
  16. package/dist/commands/review.js.map +1 -0
  17. package/dist/commands/sync.js +42 -0
  18. package/dist/commands/sync.js.map +1 -0
  19. package/dist/commands/verify.js +478 -0
  20. package/dist/commands/verify.js.map +1 -0
  21. package/dist/config/redline-json.js +187 -0
  22. package/dist/config/redline-json.js.map +1 -0
  23. package/dist/core/errors.js +25 -0
  24. package/dist/core/errors.js.map +1 -0
  25. package/dist/core/git.js +152 -0
  26. package/dist/core/git.js.map +1 -0
  27. package/dist/core/log.js +22 -0
  28. package/dist/core/log.js.map +1 -0
  29. package/dist/core/severity.js +16 -0
  30. package/dist/core/severity.js.map +1 -0
  31. package/dist/core/version.js +15 -0
  32. package/dist/core/version.js.map +1 -0
  33. package/dist/detect/scan.js +79 -0
  34. package/dist/detect/scan.js.map +1 -0
  35. package/dist/detect/stack.js +71 -0
  36. package/dist/detect/stack.js.map +1 -0
  37. package/dist/enforce/ladder.js +148 -0
  38. package/dist/enforce/ladder.js.map +1 -0
  39. package/dist/exempt/parse.js +86 -0
  40. package/dist/exempt/parse.js.map +1 -0
  41. package/dist/metrics/options.js +257 -0
  42. package/dist/metrics/options.js.map +1 -0
  43. package/dist/metrics/run.js +72 -0
  44. package/dist/metrics/run.js.map +1 -0
  45. package/dist/platforms/azure/client.js +53 -0
  46. package/dist/platforms/azure/client.js.map +1 -0
  47. package/dist/platforms/azure/index.js +69 -0
  48. package/dist/platforms/azure/index.js.map +1 -0
  49. package/dist/platforms/azure/install.js +917 -0
  50. package/dist/platforms/azure/install.js.map +1 -0
  51. package/dist/platforms/azure/policy-types.js +70 -0
  52. package/dist/platforms/azure/policy-types.js.map +1 -0
  53. package/dist/platforms/azure/verify.js +309 -0
  54. package/dist/platforms/azure/verify.js.map +1 -0
  55. package/dist/platforms/detect.js +40 -0
  56. package/dist/platforms/detect.js.map +1 -0
  57. package/dist/platforms/github/client.js +49 -0
  58. package/dist/platforms/github/client.js.map +1 -0
  59. package/dist/platforms/github/index.js +54 -0
  60. package/dist/platforms/github/index.js.map +1 -0
  61. package/dist/platforms/github/install.js +558 -0
  62. package/dist/platforms/github/install.js.map +1 -0
  63. package/dist/platforms/github/push.js +102 -0
  64. package/dist/platforms/github/push.js.map +1 -0
  65. package/dist/platforms/github/remote.js +36 -0
  66. package/dist/platforms/github/remote.js.map +1 -0
  67. package/dist/platforms/github/verify.js +366 -0
  68. package/dist/platforms/github/verify.js.map +1 -0
  69. package/dist/platforms/http.js +58 -0
  70. package/dist/platforms/http.js.map +1 -0
  71. package/dist/platforms/pull-request-templates.js +157 -0
  72. package/dist/platforms/pull-request-templates.js.map +1 -0
  73. package/dist/platforms/remote.js +21 -0
  74. package/dist/platforms/remote.js.map +1 -0
  75. package/dist/platforms/resolve.js +69 -0
  76. package/dist/platforms/resolve.js.map +1 -0
  77. package/dist/platforms/shape.js +19 -0
  78. package/dist/platforms/shape.js.map +1 -0
  79. package/dist/platforms/types.js +24 -0
  80. package/dist/platforms/types.js.map +1 -0
  81. package/dist/policy/checks.js +91 -0
  82. package/dist/policy/checks.js.map +1 -0
  83. package/dist/policy/diff.js +50 -0
  84. package/dist/policy/diff.js.map +1 -0
  85. package/dist/registry/discover.js +74 -0
  86. package/dist/registry/discover.js.map +1 -0
  87. package/dist/registry/serialize.js +41 -0
  88. package/dist/registry/serialize.js.map +1 -0
  89. package/dist/registry/types.js +2 -0
  90. package/dist/registry/types.js.map +1 -0
  91. package/dist/remove/host.js +294 -0
  92. package/dist/remove/host.js.map +1 -0
  93. package/dist/render/commands.js +139 -0
  94. package/dist/render/commands.js.map +1 -0
  95. package/dist/render/manifest.js +82 -0
  96. package/dist/render/manifest.js.map +1 -0
  97. package/dist/render/markers.js +166 -0
  98. package/dist/render/markers.js.map +1 -0
  99. package/dist/render/profile.js +23 -0
  100. package/dist/render/profile.js.map +1 -0
  101. package/dist/render/standards.js +169 -0
  102. package/dist/render/standards.js.map +1 -0
  103. package/dist/render/vendors.js +199 -0
  104. package/dist/render/vendors.js.map +1 -0
  105. package/dist/review/engines/api.js +95 -0
  106. package/dist/review/engines/api.js.map +1 -0
  107. package/dist/review/engines/embedded.js +20 -0
  108. package/dist/review/engines/embedded.js.map +1 -0
  109. package/dist/review/engines/types.js +2 -0
  110. package/dist/review/engines/types.js.map +1 -0
  111. package/dist/review/glob.js +29 -0
  112. package/dist/review/glob.js.map +1 -0
  113. package/dist/review/prompt.js +45 -0
  114. package/dist/review/prompt.js.map +1 -0
  115. package/dist/review/rules.js +25 -0
  116. package/dist/review/rules.js.map +1 -0
  117. package/dist/review/schema.js +84 -0
  118. package/dist/review/schema.js.map +1 -0
  119. package/dist/review/scope.js +27 -0
  120. package/dist/review/scope.js.map +1 -0
  121. package/dist/sarif/map.js +58 -0
  122. package/dist/sarif/map.js.map +1 -0
  123. package/dist/sarif/parse.js +88 -0
  124. package/dist/sarif/parse.js.map +1 -0
  125. package/dist/sarif/types.js +2 -0
  126. package/dist/sarif/types.js.map +1 -0
  127. package/dist/sync/host.js +21 -0
  128. package/dist/sync/host.js.map +1 -0
  129. package/dist/sync/plan.js +47 -0
  130. package/dist/sync/plan.js.map +1 -0
  131. package/dist/sync/render.js +57 -0
  132. package/dist/sync/render.js.map +1 -0
  133. package/dist/sync/run.js +118 -0
  134. package/dist/sync/run.js.map +1 -0
  135. package/dist/verify/host.js +52 -0
  136. package/dist/verify/host.js.map +1 -0
  137. package/dist/verify/remote.js +146 -0
  138. package/dist/verify/remote.js.map +1 -0
  139. package/package.json +52 -0
  140. package/platforms/azure/gate-template.yml +105 -0
  141. package/rulesets/redline-org-ruleset.json +46 -0
  142. package/rulesets/redline-ruleset.json +49 -0
  143. package/scripts/assign-rule-ids.mjs +129 -0
  144. package/scripts/build-baseline.mjs +124 -0
  145. package/scripts/build-correlation.mjs +74 -0
  146. package/scripts/build-dashboard.mjs +584 -0
  147. package/scripts/build-digest.mjs +164 -0
  148. package/scripts/build-inbox.mjs +133 -0
  149. package/scripts/build-registry.mjs +42 -0
  150. package/scripts/build-roi.mjs +181 -0
  151. package/scripts/check-pins.mjs +88 -0
  152. package/scripts/collect-telemetry.mjs +300 -0
  153. package/scripts/lib/__tests__/baseline.test.mjs +132 -0
  154. package/scripts/lib/__tests__/correlate.test.mjs +131 -0
  155. package/scripts/lib/__tests__/dora.test.mjs +110 -0
  156. package/scripts/lib/__tests__/exemptions.test.mjs +85 -0
  157. package/scripts/lib/__tests__/metrics-scanner.test.mjs +65 -0
  158. package/scripts/lib/__tests__/sarif.test.mjs +125 -0
  159. package/scripts/lib/__tests__/spend.test.mjs +64 -0
  160. package/scripts/lib/baseline.mjs +156 -0
  161. package/scripts/lib/correlate.mjs +125 -0
  162. package/scripts/lib/dora.mjs +133 -0
  163. package/scripts/lib/exemptions.mjs +79 -0
  164. package/scripts/lib/metrics.mjs +172 -0
  165. package/scripts/lib/rules.mjs +107 -0
  166. package/scripts/lib/sarif.mjs +108 -0
  167. package/scripts/lib/spend.mjs +69 -0
  168. package/scripts/measure-context.mjs +101 -0
  169. package/scripts/render-self.mjs +18 -0
  170. package/scripts/score-seeds.mjs +294 -0
  171. package/scripts/validate.mjs +394 -0
  172. package/standards/core.md +124 -0
  173. package/standards/manifest.json +214 -0
  174. package/standards/stacks/csharp.md +29 -0
  175. package/standards/stacks/go.md +30 -0
  176. package/standards/stacks/java.md +30 -0
  177. package/standards/stacks/javascript.md +42 -0
  178. package/standards/stacks/kotlin.md +27 -0
  179. package/standards/stacks/microservices.md +37 -0
  180. package/standards/stacks/nodejs.md +34 -0
  181. package/standards/stacks/python.md +29 -0
  182. package/standards/stacks/react-native.md +29 -0
  183. package/standards/stacks/react.md +46 -0
  184. package/standards/stacks/swift.md +26 -0
  185. package/standards/stacks/terraform.md +27 -0
  186. package/templates/CODEOWNERS +29 -0
  187. package/templates/azure/pull_request_template.md +72 -0
  188. package/templates/github/pull_request_template.md +72 -0
  189. package/templates/redline.yml +35 -0
  190. package/templates/repo-context.md +64 -0
  191. package/workflows/dashboard.yml +119 -0
  192. package/workflows/inbox.yml +97 -0
  193. package/workflows/redline-collect.yml +61 -0
  194. package/workflows/redline-gate.yml +301 -0
  195. package/workflows/redline-sync.yml +79 -0
  196. package/workflows/seed-canary.yml +231 -0
  197. package/workflows/verify-onboarding.yml +115 -0
  198. package/workflows/weekly-digest.yml +78 -0
@@ -0,0 +1,294 @@
1
+ import { createGit } from "../core/git.js";
2
+ import { RedlineError } from "../core/errors.js";
3
+ import { parseRemote } from "../platforms/detect.js";
4
+ import { createAzureClient } from "../platforms/azure/client.js";
5
+ import { createGitHubClient } from "../platforms/github/client.js";
6
+ import { RULESET_NAME } from "../platforms/github/install.js";
7
+ import { AZURE_STATUS_GENRE, AZURE_STATUS_NAME, POLICY_TYPE_NAMES, REDLINE_POLICY_MARKER, resolvePolicyTypeIds, } from "../platforms/azure/policy-types.js";
8
+ import { isNonNullObject, isSuccess } from "../platforms/shape.js";
9
+ // CONTRACT with GATE_LABELS in cli/platforms/github/install.ts: these are the
10
+ // three labels the gate install creates, with the descriptions it gives them.
11
+ // The description is what makes deletion safe. `no-adr` carries no Redline
12
+ // prefix at all and is exactly the name a team may already have used, and
13
+ // GitHub answers the install's POST with 422 either way — so the install
14
+ // cannot record whether it created one or found one. The description can still
15
+ // answer it: a label still carrying the text Redline wrote is Redline's, and
16
+ // one carrying anything else is the repository's own and is left in place.
17
+ const REDLINE_LABELS = [
18
+ { name: 'no-adr', description: 'PR intentionally ships without an ADR' },
19
+ { name: 'redline-exempt', description: 'Gate process checks soft-failed with reviewer sign-off' },
20
+ { name: 'redline-sync', description: 'Automated standards sync from the Redline source repo' },
21
+ ];
22
+ // CONTRACT with cli/platforms/github/install.ts's applyPolicy: the property it
23
+ // sets. GitHub removes a property value when it is PATCHed as null.
24
+ const REPO_PROPERTY = 'redline';
25
+ // CONTRACT with GATE_DEFINITION_NAME/FOLDER and GATE_YAML_FILENAME in
26
+ // cli/platforms/azure/install.ts. All three together are what
27
+ // `ensureGateBuildDefinition` uses to recognise its own definition, and the
28
+ // same tuple is what this file reports on.
29
+ const AZURE_GATE_DEFINITION = '\\Redline\\redline-gate';
30
+ const OUTCOME_RANK = {
31
+ denied: 4,
32
+ unknown: 3,
33
+ unsupported: 2,
34
+ already: 1,
35
+ applied: 0,
36
+ };
37
+ // Several host calls fold into one capability the operator reads — three label
38
+ // deletions, several Azure policy deletions. Ranked by how actionable the
39
+ // status is rather than by HTTP status number, so a definite refusal on one
40
+ // call is never masked by a larger number on another. Same table and same
41
+ // reasoning as both install adapters.
42
+ function worstOutcome(outcomes) {
43
+ const [first, ...rest] = outcomes;
44
+ if (!first)
45
+ throw new Error('worstOutcome requires at least one outcome');
46
+ return rest.reduce((worst, next) => (OUTCOME_RANK[next.status] > OUTCOME_RANK[worst.status] ? next : worst), first);
47
+ }
48
+ // Every DELETE below is issued only after a read confirmed the object is there,
49
+ // so a 404 on the delete itself is not "already gone": GitHub answers 404
50
+ // rather than 403 on an admin endpoint a fine-grained token cannot reach, the
51
+ // same reading writeOutcome takes in cli/platforms/github/install.ts. Reporting
52
+ // it as success would tell an operator their ruleset is gone when it is not.
53
+ function deleteOutcome(capability, status, detail) {
54
+ if (isSuccess(status))
55
+ return { capability, status: 'applied', detail };
56
+ if (status === 401 || status === 403 || status === 404) {
57
+ return { capability, status: 'denied', detail: `${detail} (needs repository admin)` };
58
+ }
59
+ return { capability, status: 'denied', detail: `${detail} (HTTP ${status})` };
60
+ }
61
+ // A read that did not answer. It cannot be `unknown`: `unknown` never reaches
62
+ // pendingAdmin (isPending is exactly `denied`), and a repository whose Redline
63
+ // ruleset could not even be listed has host state left behind that somebody has
64
+ // to go and remove. The detail says it was the read that failed, so nobody goes
65
+ // looking for a delete that was never attempted.
66
+ function unreadable(capability, status, what) {
67
+ return {
68
+ capability,
69
+ status: 'denied',
70
+ detail: `${what} could not be read (HTTP ${status}), so nothing was removed — ` +
71
+ 'an administrator has to take it away by hand',
72
+ };
73
+ }
74
+ function parseNamedObjects(body) {
75
+ if (!Array.isArray(body))
76
+ return null;
77
+ const parsed = [];
78
+ for (const item of body) {
79
+ if (!isNonNullObject(item) || typeof item['id'] !== 'number' || typeof item['name'] !== 'string') {
80
+ return null;
81
+ }
82
+ parsed.push({ id: item['id'], name: item['name'] });
83
+ }
84
+ return parsed;
85
+ }
86
+ function parseLabelDescription(body) {
87
+ if (!isNonNullObject(body))
88
+ return null;
89
+ const description = body['description'];
90
+ return typeof description === 'string' ? description : '';
91
+ }
92
+ export function createGitHubWithdrawal(client) {
93
+ const repoPath = (ref) => `/repos/${ref.org}/${ref.repo}`;
94
+ async function withdrawRuleset(ref) {
95
+ const listed = await client.rest('GET', `${repoPath(ref)}/rulesets`);
96
+ if (!isSuccess(listed.status)) {
97
+ return unreadable('merge-policy', listed.status, `the branch rulesets on ${ref.repo}`);
98
+ }
99
+ const rulesets = parseNamedObjects(listed.body);
100
+ if (rulesets === null) {
101
+ throw new RedlineError('host', 'GitHub returned an unexpected shape for the rulesets list');
102
+ }
103
+ // By name, which is the only attribution a ruleset carries. A ruleset a
104
+ // human named anything else is theirs even if it requires the Redline
105
+ // check — that is a policy decision they made, and taking it away is not
106
+ // this command's to do.
107
+ const mine = rulesets.find((ruleset) => ruleset.name === RULESET_NAME);
108
+ if (!mine) {
109
+ return {
110
+ capability: 'merge-policy',
111
+ status: 'already',
112
+ detail: `no ruleset named "${RULESET_NAME}" on this repository — nothing to remove`,
113
+ };
114
+ }
115
+ const deleted = await client.rest('DELETE', `${repoPath(ref)}/rulesets/${mine.id}`);
116
+ return deleteOutcome('merge-policy', deleted.status, `branch ruleset "${RULESET_NAME}" (and with it the required Redline check)`);
117
+ }
118
+ async function withdrawLabels(ref) {
119
+ const notes = [];
120
+ const outcomes = [];
121
+ for (const label of REDLINE_LABELS) {
122
+ const path = `${repoPath(ref)}/labels/${label.name}`;
123
+ const read = await client.rest('GET', path);
124
+ if (read.status === 404)
125
+ continue; // not on this repository at all
126
+ if (!isSuccess(read.status)) {
127
+ outcomes.push(unreadable('labels', read.status, `the "${label.name}" label`));
128
+ continue;
129
+ }
130
+ const description = parseLabelDescription(read.body);
131
+ if (description === null) {
132
+ throw new RedlineError('host', 'GitHub returned an unexpected shape for a label');
133
+ }
134
+ if (description !== label.description) {
135
+ notes.push(`the "${label.name}" label was left in place: its description is no longer the one Redline ` +
136
+ 'wrote, so this repository has made it its own');
137
+ continue;
138
+ }
139
+ const deleted = await client.rest('DELETE', path);
140
+ outcomes.push(deleteOutcome('labels', deleted.status, `label "${label.name}"`));
141
+ }
142
+ if (outcomes.length === 0) {
143
+ return {
144
+ outcome: {
145
+ capability: 'labels',
146
+ status: 'already',
147
+ detail: 'no label still carrying a Redline description — nothing to remove',
148
+ },
149
+ notes,
150
+ };
151
+ }
152
+ return { outcome: worstOutcome(outcomes), notes };
153
+ }
154
+ return {
155
+ host: 'github',
156
+ async withdraw(ref) {
157
+ const ruleset = await withdrawRuleset(ref);
158
+ const labels = await withdrawLabels(ref);
159
+ // Removed by PATCHing the value to null, which is how GitHub deletes a
160
+ // repository property value. The registry derives the estate by walking
161
+ // for this property, so leaving it set is what keeps a removed repository
162
+ // showing up as onboarded.
163
+ const property = await client.rest('PATCH', `${repoPath(ref)}/properties/values`, {
164
+ properties: [{ property_name: REPO_PROPERTY, value: null }],
165
+ });
166
+ return {
167
+ outcomes: [
168
+ ruleset,
169
+ labels.outcome,
170
+ deleteOutcome('repo-property', property.status, `repository property "${REPO_PROPERTY}"`),
171
+ ],
172
+ notes: labels.notes,
173
+ };
174
+ },
175
+ };
176
+ }
177
+ function parsePolicyConfigurations(body) {
178
+ if (!isNonNullObject(body) || !Array.isArray(body['value']))
179
+ return null;
180
+ const configs = [];
181
+ for (const item of body['value']) {
182
+ if (!isNonNullObject(item) || typeof item['id'] !== 'number')
183
+ return null;
184
+ const type = item['type'];
185
+ if (!isNonNullObject(type) || typeof type['id'] !== 'string')
186
+ return null;
187
+ const settings = item['settings'];
188
+ if (!isNonNullObject(settings))
189
+ return null;
190
+ configs.push({ id: item['id'], typeId: type['id'], settings });
191
+ }
192
+ return configs;
193
+ }
194
+ export function createAzureWithdrawal(client) {
195
+ return {
196
+ host: 'azure',
197
+ async withdraw(ref) {
198
+ const project = ref.project;
199
+ const repoId = ref.repoId;
200
+ if (project === undefined || repoId === undefined) {
201
+ throw new RedlineError('usage', 'an Azure DevOps repository needs a project and its id');
202
+ }
203
+ const listed = await client.request('GET', `/${project}/_apis/policy/configurations`);
204
+ if (!isSuccess(listed.status)) {
205
+ return {
206
+ outcomes: [unreadable('merge-policy', listed.status, 'the branch policies on this project')],
207
+ notes: [],
208
+ };
209
+ }
210
+ const configs = parsePolicyConfigurations(listed.body);
211
+ if (configs === null) {
212
+ throw new RedlineError('host', 'Azure DevOps returned an unexpected shape for policy configurations');
213
+ }
214
+ const types = await resolvePolicyTypeIds(client, project);
215
+ const statusTypeId = types[POLICY_TYPE_NAMES.status];
216
+ // Scoped to THIS repository, and marked as Redline's. Both halves matter:
217
+ // policy configurations are project-wide, so a sibling repository's
218
+ // Redline policies are in the same list and are not this run's to delete.
219
+ const coversThisRepo = (config) => {
220
+ const scope = config.settings['scope'];
221
+ if (!Array.isArray(scope))
222
+ return false;
223
+ return scope.some((entry) => isNonNullObject(entry) && entry['repositoryId'] === repoId);
224
+ };
225
+ // The displayName marker every policy `redline init` writes carries, plus
226
+ // the genre/name pair that identifies the gate Status policy — which
227
+ // predates the marker, so a repository onboarded by an earlier release is
228
+ // still recognised rather than abandoned. Exactly the two tests
229
+ // cli/platforms/azure/install.ts uses to decide a policy is its own.
230
+ const mine = (config) => {
231
+ const displayName = config.settings['displayName'];
232
+ if (typeof displayName === 'string' && displayName.startsWith(REDLINE_POLICY_MARKER)) {
233
+ return true;
234
+ }
235
+ return (config.typeId === statusTypeId &&
236
+ config.settings['statusGenre'] === AZURE_STATUS_GENRE &&
237
+ config.settings['statusName'] === AZURE_STATUS_NAME);
238
+ };
239
+ const targets = configs.filter((config) => coversThisRepo(config) && mine(config));
240
+ const outcomes = [];
241
+ for (const config of targets) {
242
+ const deleted = await client.request('DELETE', `/${project}/_apis/policy/configurations/${config.id}`);
243
+ outcomes.push(deleteOutcome('merge-policy', deleted.status, `branch policy ${config.id}`));
244
+ }
245
+ return {
246
+ outcomes: [
247
+ outcomes.length === 0
248
+ ? {
249
+ capability: 'merge-policy',
250
+ status: 'already',
251
+ detail: `no branch policy carrying "${REDLINE_POLICY_MARKER}" on this repository — nothing to remove`,
252
+ }
253
+ : worstOutcome(outcomes),
254
+ {
255
+ capability: 'repo-property',
256
+ status: 'unsupported',
257
+ detail: 'Azure DevOps has no repository properties, so there is none to clear',
258
+ },
259
+ {
260
+ capability: 'labels',
261
+ status: 'unsupported',
262
+ detail: 'Azure DevOps creates pull request labels on use rather than declaring them on the ' +
263
+ 'repository, so there is no label object to remove',
264
+ },
265
+ ],
266
+ // Left standing on purpose. Deleting a build definition deletes its run
267
+ // history with it, and that history is the repository's record of what
268
+ // ran on which pull request — losing it is a bigger change than
269
+ // removing Redline. The Build Validation policy above is gone, so the
270
+ // definition no longer queues on anything.
271
+ notes: [
272
+ `the "${AZURE_GATE_DEFINITION}" pipeline definition is still registered and is yours to ` +
273
+ 'delete: removing it would delete its run history too, and nothing queues it now that ' +
274
+ 'the Build Validation policy is gone',
275
+ ],
276
+ };
277
+ },
278
+ };
279
+ }
280
+ /**
281
+ * The withdrawal port for whichever host this checkout belongs to. It reads the
282
+ * remote the same way cli/platforms/resolve.ts does, and for the same reason —
283
+ * the git remote is the only thing that says which host a working tree is on.
284
+ */
285
+ export function createHostWithdrawal(cwd, deps = {}) {
286
+ const gitFor = deps.gitFor ?? ((dir) => createGit(dir));
287
+ const identity = parseRemote(gitFor(cwd).remoteUrl());
288
+ if (identity.host === 'github') {
289
+ return createGitHubWithdrawal((deps.makeGitHubClient ?? createGitHubClient)());
290
+ }
291
+ const makeAzure = deps.makeAzureClient ?? ((org) => createAzureClient(org));
292
+ return createAzureWithdrawal(makeAzure(identity.org));
293
+ }
294
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../../cli/remove/host.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,139 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
3
+ import { dirname, join } from 'node:path';
4
+ import { RedlineError } from "../core/errors.js";
5
+ import { wrapBlock } from "./markers.js";
6
+ import { stripBlock } from "./standards.js";
7
+ const FRONTMATTER = /^---\n([\s\S]*?)\n---\n?/;
8
+ export function loadCommands(root) {
9
+ const dir = join(root, 'commands');
10
+ return readdirSync(dir)
11
+ .filter((f) => f.endsWith('.md'))
12
+ .map((file) => {
13
+ const raw = readFileSync(join(dir, file), 'utf8');
14
+ const match = FRONTMATTER.exec(raw);
15
+ const description = /description:\s*(.+)/.exec(match?.[1] ?? '')?.[1]?.trim() ?? '';
16
+ return {
17
+ name: file.replace(/\.md$/, ''),
18
+ description,
19
+ body: raw.slice(match?.[0].length ?? 0).trimStart(),
20
+ };
21
+ });
22
+ }
23
+ // The header says whose it is. Nothing about the SHAPE of a frontmatter block
24
+ // tells Redline's apart from a human's — a team's own command file can carry an
25
+ // identical lone `description:` key — so recognising it by shape claimed their
26
+ // bytes. Marking what Redline owns is the answer markers.ts already gives for
27
+ // the body: an indeterminate read is not an answer, so this makes it
28
+ // determinate. It goes below the keys, not above them, because the tools read
29
+ // the first key of the block.
30
+ const MANAGED_BY = '# Managed by Redline; regenerate with `redline init` rather than editing here.';
31
+ const MANAGED_HEADER = /^# Managed by Redline\b/m;
32
+ const MANAGED_LINE = /^# Managed by Redline\b[^\n]*\n/m;
33
+ export const COMMAND_HOSTS = {
34
+ copilot: (cmd) => ({
35
+ path: `.github/prompts/${cmd.name}.prompt.md`,
36
+ header: `---\nmode: agent\ndescription: ${cmd.description}\n${MANAGED_BY}\n---\n`,
37
+ body: cmd.body,
38
+ }),
39
+ claude: (cmd) => ({
40
+ path: `.claude/commands/${cmd.name}.md`,
41
+ header: `---\ndescription: ${cmd.description}\n${MANAGED_BY}\n---\n`,
42
+ body: cmd.body,
43
+ }),
44
+ opencode: (cmd) => ({
45
+ path: `.opencode/command/${cmd.name}.md`,
46
+ header: `---\ndescription: ${cmd.description}\n${MANAGED_BY}\n---\n`,
47
+ body: cmd.body,
48
+ }),
49
+ cursor: (cmd) => ({ path: `.cursor/commands/${cmd.name}.md`, header: '', body: cmd.body }),
50
+ };
51
+ // What the renderer before the marker block wrote at this path: the header and
52
+ // the body with one blank line between them, and no attribution line, because
53
+ // there was none to write. Every repository already onboarded has exactly these
54
+ // bytes on disk, put there by Redline itself — merge-or-create is the right
55
+ // answer for a HUMAN's file and the wrong one for Redline's own earlier output,
56
+ // which would get its prompt appended to itself and run twice. Recomputed
57
+ // rather than pattern-matched, so it can only ever recognise a file Redline
58
+ // actually produced.
59
+ function previouslyRendered(header, body) {
60
+ const legacyHeader = header.replace(MANAGED_LINE, '');
61
+ const composed = legacyHeader === '' ? body : `${legacyHeader}\n${body}`;
62
+ return `${composed.trimEnd()}\n`;
63
+ }
64
+ // What `.redline.json` records for every command file Redline owns whole, and
65
+ // the only thing a later run compares that record against. The algorithm is
66
+ // therefore part of the on-disk contract: change it and every recorded
67
+ // identifier stops matching, which silently returns those repositories to the
68
+ // byte-exact fallback below.
69
+ export function contentId(text) {
70
+ return `sha256:${createHash('sha256').update(text).digest('hex')}`;
71
+ }
72
+ // `<name>` is only the filename in `commands/`, and nothing reserves that name
73
+ // in a consumer repository — `commands/review-pr.md` here would land on a
74
+ // team's own `.claude/commands/review-pr.md`. So whatever is at the path stays
75
+ // and Redline's half goes inside a marker block beside it. A `.claude/commands`
76
+ // file IS one prompt body, so `/<name>` then runs both texts concatenated; that
77
+ // is the accepted cost of not overwriting a human's prompt, and the markers are
78
+ // what keep Redline's half removable and re-renderable.
79
+ export function renderCommands(opts) {
80
+ const commands = loadCommands(opts.root);
81
+ const written = [];
82
+ const removed = [];
83
+ const contentIds = {};
84
+ for (const host of opts.hosts) {
85
+ if (!COMMAND_HOSTS[host]) {
86
+ throw new RedlineError('usage', `unknown command host "${host}". Known: ${Object.keys(COMMAND_HOSTS).join(', ')}`);
87
+ }
88
+ }
89
+ // Every host, not just the selected ones: a host that is no longer selected
90
+ // is how Redline's block gets taken back out again, which is the other half
91
+ // of being allowed to merge it into a file it does not own.
92
+ for (const [host, renderer] of Object.entries(COMMAND_HOSTS)) {
93
+ const selected = opts.hosts.includes(host);
94
+ for (const command of commands) {
95
+ const { path, header, body } = renderer(command);
96
+ const target = join(opts.out, path);
97
+ const current = existsSync(target) ? readFileSync(target, 'utf8') : null;
98
+ // Throws rather than guessing on a half-edited marker pair or a block
99
+ // hidden under an unclosed fence — see markers.ts. Nothing is written.
100
+ const outside = current === null ? null : stripBlock(current, path);
101
+ // Redline's to rewrite whole: the file is nothing but its block, or what
102
+ // sits outside the block carries Redline's own attribution line, or the
103
+ // file predates the block entirely and is byte-for-byte what Redline
104
+ // last rendered there.
105
+ // The recorded identifier is asked first because it is the only one of
106
+ // the three that does not move when `commands/<name>.md` changes here.
107
+ const recorded = opts.known?.[path];
108
+ const ownedWhole = outside === null ||
109
+ (outside !== current && MANAGED_HEADER.test(outside)) ||
110
+ (current !== null &&
111
+ outside === current &&
112
+ (recorded === contentId(current) || current === previouslyRendered(header, body)));
113
+ if (!selected) {
114
+ if (current === null || outside === current)
115
+ continue; // never Redline's — brownfield rule
116
+ if (!opts.check) {
117
+ if (ownedWhole)
118
+ rmSync(target);
119
+ else
120
+ writeFileSync(target, outside);
121
+ }
122
+ removed.push(path);
123
+ continue;
124
+ }
125
+ const next = wrapBlock(current === null || ownedWhole ? header : current, body, path);
126
+ if (current === null || ownedWhole)
127
+ contentIds[path] = contentId(next);
128
+ if (current === next)
129
+ continue;
130
+ if (!opts.check) {
131
+ mkdirSync(dirname(target), { recursive: true });
132
+ writeFileSync(target, next);
133
+ }
134
+ written.push(path);
135
+ }
136
+ }
137
+ return { written, removed, contentIds };
138
+ }
139
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../cli/render/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { RedlineError } from "../core/errors.js";
4
+ function isNonNullObject(value) {
5
+ return typeof value === 'object' && value !== null;
6
+ }
7
+ export function parseManifest(raw) {
8
+ if (!isNonNullObject(raw)) {
9
+ throw new RedlineError('usage', 'standards manifest is not a JSON object');
10
+ }
11
+ const version = raw['version'];
12
+ if (typeof version !== 'string') {
13
+ throw new RedlineError('usage', 'standards manifest is missing a string "version" field');
14
+ }
15
+ const core = raw['core'];
16
+ const stacks = raw['stacks'];
17
+ const profiles = raw['profiles'];
18
+ const vendors = raw['vendors'];
19
+ if (!isNonNullObject(core)) {
20
+ throw new RedlineError('usage', 'standards manifest is missing an object "core" field');
21
+ }
22
+ if (!isNonNullObject(stacks)) {
23
+ throw new RedlineError('usage', 'standards manifest is missing an object "stacks" field');
24
+ }
25
+ if (!isNonNullObject(profiles)) {
26
+ throw new RedlineError('usage', 'standards manifest is missing an object "profiles" field');
27
+ }
28
+ if (!isNonNullObject(vendors)) {
29
+ throw new RedlineError('usage', 'standards manifest is missing an object "vendors" field');
30
+ }
31
+ const coreTitle = core['title'];
32
+ const coreSource = core['source'];
33
+ if (typeof coreTitle !== 'string' || typeof coreSource !== 'string') {
34
+ throw new RedlineError('usage', 'standards manifest "core" needs string "title" and "source" fields');
35
+ }
36
+ const profileAliasesRaw = raw['profileAliases'];
37
+ if (profileAliasesRaw !== undefined && !isNonNullObject(profileAliasesRaw)) {
38
+ throw new RedlineError('usage', 'standards manifest "profileAliases" must be an object');
39
+ }
40
+ const profileAliases = (profileAliasesRaw ?? {});
41
+ const deterministicRaw = raw['deterministic'];
42
+ if (deterministicRaw !== undefined && !Array.isArray(deterministicRaw)) {
43
+ throw new RedlineError('usage', 'standards manifest "deterministic" must be an array of rule ids');
44
+ }
45
+ const deterministic = (deterministicRaw ?? []);
46
+ for (const id of deterministic) {
47
+ if (typeof id !== 'string') {
48
+ throw new RedlineError('usage', 'standards manifest "deterministic" must contain only rule ids');
49
+ }
50
+ }
51
+ return {
52
+ version,
53
+ core: { title: coreTitle, source: coreSource },
54
+ stacks: stacks,
55
+ profiles: profiles,
56
+ profileAliases,
57
+ vendors: vendors,
58
+ deterministic,
59
+ };
60
+ }
61
+ function errorCode(error) {
62
+ if (typeof error !== 'object' || error === null || !('code' in error))
63
+ return undefined;
64
+ const code = error.code;
65
+ return typeof code === 'string' ? code : undefined;
66
+ }
67
+ export function loadManifest(root) {
68
+ const path = join(root, 'standards/manifest.json');
69
+ let raw;
70
+ try {
71
+ raw = readFileSync(path, 'utf8');
72
+ }
73
+ catch (error) {
74
+ if (errorCode(error) === 'EACCES') {
75
+ throw new RedlineError('permission', `permission denied reading the standards manifest at ${path}`);
76
+ }
77
+ throw new RedlineError('usage', `cannot read the standards manifest at ${path}`);
78
+ }
79
+ const parsed = JSON.parse(raw);
80
+ return parseManifest(parsed);
81
+ }
82
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../cli/render/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAgCjD,SAAS,eAAe,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAY;IACxC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,yCAAyC,CAAC,CAAC;IAC7E,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;IAC/B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,wDAAwD,CAAC,CAAC;IAC5F,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;IAC/B,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,sDAAsD,CAAC,CAAC;IAC1F,CAAC;IACD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,wDAAwD,CAAC,CAAC;IAC5F,CAAC;IACD,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,0DAA0D,CAAC,CAAC;IAC9F,CAAC;IACD,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,yDAAyD,CAAC,CAAC;IAC7F,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAChC,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACpE,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,oEAAoE,CAAC,CAAC;IACxG,CAAC;IACD,MAAM,iBAAiB,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAChD,IAAI,iBAAiB,KAAK,SAAS,IAAI,CAAC,eAAe,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,uDAAuD,CAAC,CAAC;IAC3F,CAAC;IACD,MAAM,cAAc,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAA2B,CAAC;IAE3E,MAAM,gBAAgB,GAAG,GAAG,CAAC,eAAe,CAAC,CAAC;IAC9C,IAAI,gBAAgB,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACvE,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,iEAAiE,CAAC,CAAC;IACrG,CAAC;IACD,MAAM,aAAa,GAAG,CAAC,gBAAgB,IAAI,EAAE,CAAa,CAAC;IAC3D,KAAK,MAAM,EAAE,IAAI,aAAa,EAAE,CAAC;QAC/B,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;YAC3B,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,+DAA+D,CAAC,CAAC;QACnG,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO;QACP,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE;QAC9C,MAAM,EAAE,MAAkC;QAC1C,QAAQ,EAAE,QAAoC;QAC9C,cAAc;QACd,OAAO,EAAE,OAAoC;QAC7C,aAAa;KACd,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACxF,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,yBAAyB,CAAC,CAAC;IACnD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,SAAS,CAAC,KAAK,CAAC,KAAK,QAAQ,EAAE,CAAC;YAClC,MAAM,IAAI,YAAY,CAAC,YAAY,EAAE,uDAAuD,IAAI,EAAE,CAAC,CAAC;QACtG,CAAC;QACD,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,yCAAyC,IAAI,EAAE,CAAC,CAAC;IACnF,CAAC;IACD,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxC,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC"}