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,166 @@
1
+ import { RedlineError } from "../core/errors.js";
2
+ // Matched on this prefix alone, never on the whole BEGIN line. The rest of the
3
+ // line is attribution prose, and prose gets corrected: blocks written by older
4
+ // CLI versions are already on disk in every onboarded repository, and matching
5
+ // the full literal would stop recognising them the moment the wording changed —
6
+ // so the next run would append a second block beside the first instead of
7
+ // replacing it.
8
+ export const BEGIN_PREFIX = '<!-- REDLINE:BEGIN';
9
+ export const BEGIN = `${BEGIN_PREFIX} — generated by Redline. Do not edit inside this block. -->`;
10
+ export const END = '<!-- REDLINE:END -->';
11
+ // A fenced code block, per CommonMark: a rail of three or more backticks or
12
+ // tildes, indented up to three spaces — or sitting on a list-item line, where
13
+ // the rail is measured from the item's content column rather than the margin.
14
+ // Without that second form, a list whose fence is opened on the bullet line and
15
+ // closed at indent 2 reads as a lone opening rail, and a document that renders
16
+ // perfectly gets refused.
17
+ const FENCE = /^ {0,3}(?:(?:[-*+]|\d{1,9}[.)])[ \t]+)?(`{3,}|~{3,})(.*)$/;
18
+ // Raw HTML: a comment that spans lines, or a block tag that runs to the next
19
+ // blank line. Inside either, a rail is literal HTML content and not a fence —
20
+ // missing that hid a real block behind a pair of spurious fences and appended a
21
+ // second block beside it. This suppresses FENCE detection only, never marker
22
+ // detection: not seeing a marker is the dangerous direction, and a BEGIN/END
23
+ // line is a single-line comment that opens no block of its own.
24
+ const HTML_COMMENT_OPEN = /^ {0,3}<!--/;
25
+ const HTML_TAG_OPEN = /^ {0,3}<\/?[A-Za-z][A-Za-z0-9-]*(?:[ \t/>]|$)/;
26
+ function scanMarkers(text, trackFences) {
27
+ const begins = [];
28
+ const ends = [];
29
+ let offset = 0;
30
+ let fence = null;
31
+ let html = null;
32
+ for (const line of text.split('\n')) {
33
+ const bare = line.endsWith('\r') ? line.slice(0, -1) : line;
34
+ if (trackFences) {
35
+ if (html !== null) {
36
+ if (html === 'comment' ? bare.includes('-->') : bare.trim() === '')
37
+ html = null;
38
+ }
39
+ else if (fence === null) {
40
+ if (HTML_COMMENT_OPEN.test(bare) && !bare.includes('-->'))
41
+ html = 'comment';
42
+ else if (HTML_TAG_OPEN.test(bare))
43
+ html = 'tag';
44
+ }
45
+ }
46
+ // A closing fence must use the same character, be at least as long as the
47
+ // opening one, and carry no info string — so a ```md line inside an open
48
+ // ``` fence is content, not the close.
49
+ const fenced = trackFences && html === null ? FENCE.exec(bare) : null;
50
+ const rail = fenced?.[1];
51
+ if (rail !== undefined) {
52
+ const char = rail.slice(0, 1);
53
+ if (fence === null)
54
+ fence = { char, length: rail.length, offset };
55
+ else if (char === fence.char && rail.length >= fence.length && (fenced?.[2] ?? '').trim() === '') {
56
+ fence = null;
57
+ }
58
+ }
59
+ else if (fence === null) {
60
+ // Leading whitespace no longer hides a marker. A real block a human
61
+ // tab-indented (a paste, an autoformatter, a manual edit) used to read
62
+ // as absent, and the next run appended a silent second block beside it
63
+ // — the same failure shape a hidden fence has, just from the opposite
64
+ // direction (too little tolerance instead of too much). `begins` still
65
+ // records the START OF THE LINE: on replace, the prefix cut lands
66
+ // before the indent, so a tab-indented block is normalized back to
67
+ // column zero rather than being re-indented. `ends` records where the
68
+ // literal END text itself begins, because `stop + END.length` — used
69
+ // here and by both adapters' own `outside` split — has to land exactly
70
+ // after the marker text no matter how much whitespace preceded it.
71
+ const indent = (/^[ \t]*/.exec(bare)?.[0] ?? '').length;
72
+ const rest = bare.slice(indent);
73
+ if (rest.startsWith(BEGIN_PREFIX))
74
+ begins.push(offset);
75
+ else if (rest.startsWith(END))
76
+ ends.push(offset + indent);
77
+ }
78
+ offset += line.length + 1;
79
+ }
80
+ return { begins, ends, unterminatedFence: fence === null ? null : fence.offset };
81
+ }
82
+ const MARKER_HINT = 'Restore a single REDLINE:BEGIN … REDLINE:END pair around the generated block, or delete both ' +
83
+ 'marker lines and let the next run append a fresh block below your content. Redline made no ' +
84
+ 'change to that file.';
85
+ // Names the line rather than the repair, because the repair depends on where
86
+ // the fence is. Telling the operator to "move the REDLINE block above it" is
87
+ // unfollowable when the fence was opened inside that very block — which is what
88
+ // an unbalanced fence authored into the generated body looks like from here.
89
+ function fenceHint(text, fenceOffset) {
90
+ const line = text.slice(0, fenceOffset).split('\n').length;
91
+ return (`Close the code fence opened on line ${line}. An unclosed fence runs to the end of the ` +
92
+ 'document, so Redline cannot tell whether the REDLINE markers below it are its own block or ' +
93
+ 'an illustration inside the code. If that line sits inside Redline\'s own generated block, ' +
94
+ 'the generated content is unbalanced — fix its source, not this file. Redline made no change ' +
95
+ 'to that file.');
96
+ }
97
+ function refuse(label, problem, hint = MARKER_HINT) {
98
+ throw new RedlineError('failed', `${label} ${problem}, so Redline cannot tell which part of it is its own and will not write to it`, hint);
99
+ }
100
+ // The span Redline owns, or null when the file carries no markers at all.
101
+ // Anything in between — one marker without its pair, a pair in the wrong order,
102
+ // or more than one of either — is a file Redline must not guess about: the
103
+ // slice arithmetic would duplicate the span on every run, or delete every byte
104
+ // between a stray marker and the real block.
105
+ export function findBlock(existing, label) {
106
+ const { begins, ends, unterminatedFence } = scanMarkers(existing, true);
107
+ if (unterminatedFence !== null) {
108
+ // Reading the hidden markers as absent appends a second block on every run
109
+ // — unbounded, silent growth in exactly the files this guard exists for.
110
+ // Reading them as real splices inside what renders as a code block. Both
111
+ // are guesses about a human-owned file, so refuse. Only when the
112
+ // undecidable region actually holds a marker, though: with none, the two
113
+ // readings agree and nothing is being guessed.
114
+ const hidden = scanMarkers(existing.slice(unterminatedFence), false);
115
+ if (hidden.begins.length > 0 || hidden.ends.length > 0) {
116
+ refuse(label, 'has an unclosed code fence with REDLINE markers below it', fenceHint(existing, unterminatedFence));
117
+ }
118
+ }
119
+ if (begins.length === 0 && ends.length === 0)
120
+ return null;
121
+ if (begins.length > 1 || ends.length > 1) {
122
+ refuse(label, `has ${begins.length} REDLINE:BEGIN and ${ends.length} REDLINE:END markers where exactly one of each is expected`);
123
+ }
124
+ const start = begins[0];
125
+ const stop = ends[0];
126
+ if (start === undefined)
127
+ refuse(label, 'has a REDLINE:END marker with no matching REDLINE:BEGIN');
128
+ if (stop === undefined)
129
+ refuse(label, 'has a REDLINE:BEGIN marker with no matching REDLINE:END');
130
+ if (stop < start)
131
+ refuse(label, 'has its REDLINE:END marker before its REDLINE:BEGIN marker');
132
+ return { start, stop };
133
+ }
134
+ // Validates the file it is about to WRITE, not only the one it read. `findBlock`
135
+ // returning null is not a neutral observation — it is the instruction "append at
136
+ // end of file", and end of file can be inside an unterminated fence, or inside a
137
+ // region some future parser gap hides. Re-scanning the result and requiring the
138
+ // block to come back as the one well-formed block, at the offset it was placed
139
+ // at, checks the decision that was actually made rather than the one input it
140
+ // was made from.
141
+ function verifyWritten(result, expectedStart, label) {
142
+ const { begins, ends, unterminatedFence } = scanMarkers(result, true);
143
+ const start = begins[0];
144
+ const stop = ends[0];
145
+ if (begins.length === 1 && ends.length === 1 && start === expectedStart && stop !== undefined && stop > start) {
146
+ return result;
147
+ }
148
+ throw new RedlineError('failed', `Redline would have to write ${label} in a shape it cannot read back: the block it is about ` +
149
+ 'to write does not come back as the one well-formed REDLINE block in the file, so a later ' +
150
+ 'run could not find it again. Nothing was written.', unterminatedFence === null ? MARKER_HINT : fenceHint(result, unterminatedFence));
151
+ }
152
+ export function wrapBlock(existing, body, label) {
153
+ const block = `${BEGIN}\n\n${body.trimEnd()}\n\n${END}\n`;
154
+ if (existing === null || existing === '')
155
+ return verifyWritten(block, 0, label);
156
+ const span = findBlock(existing, label);
157
+ if (span === null) {
158
+ // Byte-for-byte on the existing content: only the separator that makes the
159
+ // appended block a paragraph of its own is added. Trimming the human's
160
+ // trailing whitespace would be a change Redline was not asked to make.
161
+ const gap = existing.endsWith('\n\n') ? '' : existing.endsWith('\n') ? '\n' : '\n\n';
162
+ return verifyWritten(`${existing}${gap}${block}`, existing.length + gap.length, label);
163
+ }
164
+ return verifyWritten(existing.slice(0, span.start) + block.trimEnd() + existing.slice(span.stop + END.length), span.start, label);
165
+ }
166
+ //# sourceMappingURL=markers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markers.js","sourceRoot":"","sources":["../../cli/render/markers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { RedlineError } from "../core/errors.js";
2
+ export function resolveProfile(manifest, name) {
3
+ const key = manifest.profileAliases[name] ?? name;
4
+ const stacks = manifest.profiles[key];
5
+ if (!stacks) {
6
+ throw new RedlineError('usage', `unknown profile "${name}". Known: ${Object.keys(manifest.profiles).join(', ')} ` +
7
+ `(aliases: ${Object.keys(manifest.profileAliases).join(', ')})`);
8
+ }
9
+ const out = [];
10
+ const visit = (id) => {
11
+ const stack = manifest.stacks[id];
12
+ if (!stack) {
13
+ throw new RedlineError('usage', `profile "${key}" references unknown stack "${id}"`);
14
+ }
15
+ for (const parent of stack.extends ?? [])
16
+ visit(parent);
17
+ if (!out.includes(id))
18
+ out.push(id);
19
+ };
20
+ stacks.forEach(visit);
21
+ return { profile: key, stacks: out };
22
+ }
23
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../cli/render/profile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAOjD,MAAM,UAAU,cAAc,CAAC,QAAkB,EAAE,IAAY;IAC7D,MAAM,GAAG,GAAG,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IAClD,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,YAAY,CACpB,OAAO,EACP,oBAAoB,IAAI,aAAa,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YAC/E,aAAa,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAClE,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,KAAK,GAAG,CAAC,EAAU,EAAQ,EAAE;QACjC,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,+BAA+B,EAAE,GAAG,CAAC,CAAC;QACvF,CAAC;QACD,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,EAAE;YAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtC,CAAC,CAAC;IACF,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACtB,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AACvC,CAAC"}
@@ -0,0 +1,169 @@
1
+ import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { loadManifest } from "./manifest.js";
4
+ import { resolveProfile } from "./profile.js";
5
+ import { END, findBlock, wrapBlock } from "./markers.js";
6
+ import { readLocalRules, VENDORS } from "./vendors.js";
7
+ import { RedlineError } from "../core/errors.js";
8
+ // The rest of a shared file once its Redline block is cut out, or `null` when
9
+ // nothing survives but whitespace, so the caller deletes the file rather than
10
+ // writing back a blank one. Mirrors wrapBlock's own contract in the other
11
+ // direction: `before` is kept byte-for-byte, and `after` only ever loses the
12
+ // single newline that trails the block itself (the append path's own
13
+ // `${END}\n`, or none at all on the replace path's `block.trimEnd()`) — never
14
+ // a byte the human wrote. Because that trailing newline is indistinguishable
15
+ // on disk from a separator wrapBlock itself inserted, stripping a block back
16
+ // out is not always the exact inverse of wrapping it in — see the round-trip
17
+ // tests. `findBlock` (markers.ts) owns the marker scan and its refusal on an
18
+ // ambiguous marker state; this only decides the byte range to keep, reusing
19
+ // that scan rather than re-parsing the file itself. Returns `existing`
20
+ // unchanged when there is no block to find, so a caller can tell "nothing
21
+ // here was ever Redline's" from "the block was removed" by identity.
22
+ export function stripBlock(existing, label) {
23
+ const span = findBlock(existing, label);
24
+ if (span === null)
25
+ return existing;
26
+ const before = existing.slice(0, span.start);
27
+ const rest = existing.slice(span.stop + END.length);
28
+ const after = rest.startsWith('\n') ? rest.slice(1) : rest;
29
+ if (before.trim() === '' && after.trim() === '')
30
+ return null;
31
+ return before + after;
32
+ }
33
+ export function render(opts) {
34
+ const { root, out, check = false } = opts;
35
+ const manifest = loadManifest(root);
36
+ const resolved = resolveProfile(manifest, opts.profile);
37
+ const requested = opts.vendors ??
38
+ Object.entries(manifest.vendors)
39
+ .filter(([, v]) => v.enabled)
40
+ .map(([k]) => k);
41
+ for (const name of requested) {
42
+ if (!VENDORS[name]) {
43
+ throw new RedlineError('usage', `unknown vendor "${name}". Known: ${Object.keys(VENDORS).join(', ')}`);
44
+ }
45
+ }
46
+ // The org manifest is the ceiling, enforced here rather than by whoever
47
+ // built `opts.vendors`: a repository's recorded selection can predate an
48
+ // org-wide disablement, and a stale record must not resurrect a vendor the
49
+ // org has since switched off.
50
+ const orgEnabled = new Set(Object.entries(manifest.vendors)
51
+ .filter(([, v]) => v.enabled)
52
+ .map(([k]) => k));
53
+ const selected = requested.filter((name) => orgEnabled.has(name));
54
+ // Read from `out`, the tree being rendered into: the repository's own rules
55
+ // live in the repository, and every vendor renderer gets the same bytes.
56
+ const ctx = {
57
+ manifest,
58
+ root,
59
+ profile: resolved.profile,
60
+ stacks: resolved.stacks,
61
+ local: readLocalRules(out),
62
+ };
63
+ const planned = new Map();
64
+ const prunes = [];
65
+ // A shared (`merge: true`) file belonging to a vendor that is not currently
66
+ // selected — by repository choice or because the org ceiling just dropped
67
+ // it. Only the block inside it is Redline's, so it needs the removal path
68
+ // below rather than the directory-scan PruneRule uses for owned files.
69
+ const deselectedMergeFiles = [];
70
+ // Every vendor's renderer runs, not just the selected ones: a PruneRule's
71
+ // directory scan is how a vendor's own generated files get cleaned up once
72
+ // it is no longer selected at all, and that only happens if its rule is in
73
+ // `prunes` regardless of selection.
74
+ for (const name of Object.keys(VENDORS)) {
75
+ const renderer = VENDORS[name];
76
+ const result = renderer(ctx);
77
+ prunes.push(...result.prune);
78
+ if (selected.includes(name)) {
79
+ for (const [path, file] of result.files)
80
+ planned.set(path, file);
81
+ }
82
+ else {
83
+ for (const [path, file] of result.files) {
84
+ if (file.merge)
85
+ deselectedMergeFiles.push(path);
86
+ }
87
+ }
88
+ }
89
+ const written = [];
90
+ const removed = [];
91
+ const staleWritten = [];
92
+ const staleRemovals = [];
93
+ for (const [relPath, spec] of planned) {
94
+ const target = join(out, relPath);
95
+ const current = existsSync(target) ? readFileSync(target, 'utf8') : null;
96
+ const next = spec.merge ? wrapBlock(current, spec.body, relPath) : `${spec.body.trimEnd()}\n`;
97
+ if (current === next)
98
+ continue;
99
+ if (check) {
100
+ staleWritten.push(relPath);
101
+ continue;
102
+ }
103
+ mkdirSync(dirname(target), { recursive: true });
104
+ writeFileSync(target, next);
105
+ written.push(relPath);
106
+ }
107
+ // Deselected vendors' shared files: strip the block, deleting the file
108
+ // outright when nothing else is left. Always a removal, never a write — a
109
+ // deselect is not content Redline is choosing to keep.
110
+ for (const relPath of deselectedMergeFiles) {
111
+ const target = join(out, relPath);
112
+ if (!existsSync(target))
113
+ continue;
114
+ const current = readFileSync(target, 'utf8');
115
+ const stripped = stripBlock(current, relPath);
116
+ if (stripped === current)
117
+ continue; // no Redline block here — brownfield rule
118
+ if (check) {
119
+ staleRemovals.push(relPath);
120
+ continue;
121
+ }
122
+ if (stripped === null)
123
+ rmSync(target);
124
+ else
125
+ writeFileSync(target, stripped);
126
+ removed.push(relPath);
127
+ }
128
+ for (const rule of prunes) {
129
+ const abs = join(out, rule.dir);
130
+ if (!existsSync(abs))
131
+ continue;
132
+ for (const file of readdirSync(abs)) {
133
+ if (!rule.matches(file))
134
+ continue;
135
+ const relPath = join(rule.dir, file);
136
+ // A directory-shaped artifact is still planned when anything planned lives
137
+ // inside it. Asking whether the directory itself is planned is always
138
+ // false, which would delete every one of them on every render.
139
+ const stillPlanned = rule.directories
140
+ ? [...planned.keys()].some((p) => p.startsWith(`${relPath}/`))
141
+ : planned.has(relPath);
142
+ if (stillPlanned)
143
+ continue;
144
+ if (check) {
145
+ staleRemovals.push(relPath);
146
+ continue;
147
+ }
148
+ rmSync(join(abs, file), rule.directories ? { recursive: true, force: true } : {});
149
+ removed.push(relPath);
150
+ }
151
+ }
152
+ const stale = [
153
+ ...staleWritten,
154
+ ...staleRemovals.map((relPath) => `${relPath} (stale, should be removed)`),
155
+ ];
156
+ return {
157
+ ...resolved,
158
+ written,
159
+ removed,
160
+ stale,
161
+ staleWritten,
162
+ staleRemovals,
163
+ managed: [...planned.keys()],
164
+ localRuleFiles: [...planned]
165
+ .filter(([, file]) => file.localRules === true)
166
+ .map(([relPath]) => relPath),
167
+ };
168
+ }
169
+ //# sourceMappingURL=standards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standards.js","sourceRoot":"","sources":["../../cli/render/standards.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,199 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { BEGIN, BEGIN_PREFIX, END, findBlock } from "./markers.js";
4
+ export const PREFIX = 'redline-';
5
+ // The repository's own rules. A human owns this file outright: Redline reads
6
+ // it, never writes it, never prunes it, and never fails a run over what is in
7
+ // it. It is rendered INSIDE the Redline block precisely because a human's edit
8
+ // to the block itself does not survive the next render and this has to.
9
+ export const LOCAL_RULES_FILE = '.redline/local.md';
10
+ const read = (root, relPath) => readFileSync(join(root, relPath), 'utf8').trimEnd();
11
+ const stackBody = (ctx, id) => read(ctx.root, ctx.manifest.stacks[id].source);
12
+ const header = (ctx, stacks) => `<!-- Redline v${ctx.manifest.version} · profile: ${ctx.profile} · stacks: ${stacks.join(', ')} -->`;
13
+ // Precedence has to be stated in the artifact itself, in words the tool acts
14
+ // on: two rule sets sitting side by side with nothing to resolve a conflict
15
+ // between them is the gap this section exists to close.
16
+ const PRECEDENCE = [
17
+ `The rules below come from this repository's own \`${LOCAL_RULES_FILE}\`, not from the org`,
18
+ 'standard. Where one of them conflicts with anything above, the repository\'s own rules win',
19
+ 'here. Everything above that they do not contradict still applies.',
20
+ ].join('\n');
21
+ export const LOCAL_HEADING = '# Repository-local rules';
22
+ export function localSection(local) {
23
+ return `---\n\n${LOCAL_HEADING}\n\n${PRECEDENCE}\n\n${local}`;
24
+ }
25
+ const withLocal = (ctx, body) => ctx.local === null ? body : `${body}\n\n${localSection(ctx.local)}`;
26
+ // A REDLINE marker line and an unclosed code fence are the two shapes in a
27
+ // human's markdown that reach markers.ts as structure rather than as prose: the
28
+ // first makes a second marker pair, which wrapBlock refuses, and the second
29
+ // swallows the END marker written below it. Neither may cost the run, because
30
+ // this file is not Redline's to validate. So the marker text is escaped to the
31
+ // characters it renders as, and whether what is left can still be read back is
32
+ // asked of markers.ts itself rather than of a second parser here — anything it
33
+ // cannot read is quoted, which no fence and no marker survives.
34
+ //
35
+ // Built from markers.ts's own literals rather than restating the marker shape:
36
+ // BEGIN_PREFIX exists because the marker wording changes, and a second copy of
37
+ // it here would stop escaping the day it does — which is the one direction
38
+ // that costs a run.
39
+ const escapeRegExp = (literal) => literal.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
40
+ const MARKER_LINE = new RegExp(`^([ \\t]*)(${[BEGIN_PREFIX, END].map(escapeRegExp).join('|')})`, 'gm');
41
+ const readable = (candidate) => {
42
+ try {
43
+ return findBlock(`${BEGIN}\n${candidate}\n${END}\n`, LOCAL_RULES_FILE) !== null;
44
+ }
45
+ catch {
46
+ return false;
47
+ }
48
+ };
49
+ const quote = (text) => text
50
+ .split('\n')
51
+ .map((line) => (line.trim() === '' ? '>' : `> ${line}`))
52
+ .join('\n');
53
+ export function readLocalRules(out) {
54
+ const path = join(out, LOCAL_RULES_FILE);
55
+ if (!existsSync(path))
56
+ return null;
57
+ const raw = readFileSync(path, 'utf8').trim();
58
+ if (raw === '')
59
+ return null;
60
+ const escaped = raw.replace(MARKER_LINE, (_match, indent, marker) => `${indent}&lt;${marker.slice(1)}`);
61
+ return readable(escaped) ? escaped : quote(escaped);
62
+ }
63
+ const copilot = (ctx) => {
64
+ const files = new Map();
65
+ files.set('.github/copilot-instructions.md', {
66
+ merge: true,
67
+ localRules: true,
68
+ body: withLocal(ctx, `${header(ctx, ctx.stacks)}\n\n${read(ctx.root, ctx.manifest.core.source)}`),
69
+ });
70
+ for (const id of ctx.stacks) {
71
+ const stack = ctx.manifest.stacks[id];
72
+ files.set(`.github/instructions/${PREFIX}${id}.instructions.md`, {
73
+ body: `---\napplyTo: ${JSON.stringify(stack.globs.join(','))}\n---\n\n` +
74
+ `${header(ctx, [id])}\n\n${stackBody(ctx, id)}`,
75
+ });
76
+ }
77
+ return {
78
+ files,
79
+ prune: [
80
+ {
81
+ dir: '.github/instructions',
82
+ matches: (f) => f.startsWith(PREFIX) && f.endsWith('.instructions.md'),
83
+ },
84
+ ],
85
+ };
86
+ };
87
+ const demote = (md) => md.replace(/^(#{1,5}) /gm, '#$1 ');
88
+ const agents = (ctx) => {
89
+ const sections = ctx.stacks.map((id) => {
90
+ const scope = ctx.manifest.stacks[id].globs.map((g) => `\`${g}\``).join(', ');
91
+ return `${demote(stackBody(ctx, id))}\n\n_Applies to: ${scope}_`;
92
+ });
93
+ const body = [
94
+ header(ctx, ctx.stacks),
95
+ '',
96
+ read(ctx.root, ctx.manifest.core.source),
97
+ '',
98
+ '---',
99
+ '',
100
+ '# Stack rules',
101
+ '',
102
+ sections.join('\n\n---\n\n'),
103
+ ].join('\n');
104
+ return {
105
+ files: new Map([['AGENTS.md', { merge: true, localRules: true, body: withLocal(ctx, body) }]]),
106
+ prune: [],
107
+ };
108
+ };
109
+ const claude = (ctx) => ({
110
+ files: new Map([
111
+ [
112
+ 'CLAUDE.md',
113
+ {
114
+ merge: true,
115
+ localRules: true,
116
+ body: withLocal(ctx, [
117
+ 'Engineering standards and review rules for this repository are defined by Redline',
118
+ 'and rendered into `AGENTS.md`. They are binding for all work in this repo.',
119
+ '',
120
+ '@AGENTS.md',
121
+ ].join('\n')),
122
+ },
123
+ ],
124
+ ]),
125
+ prune: [],
126
+ });
127
+ const cursor = (ctx) => {
128
+ const files = new Map();
129
+ files.set(`.cursor/rules/${PREFIX}core.mdc`, {
130
+ localRules: true,
131
+ body: `---\ndescription: Redline core standards\nalwaysApply: true\n---\n\n` +
132
+ withLocal(ctx, `${header(ctx, ctx.stacks)}\n\n${read(ctx.root, ctx.manifest.core.source)}`),
133
+ });
134
+ for (const id of ctx.stacks) {
135
+ const stack = ctx.manifest.stacks[id];
136
+ files.set(`.cursor/rules/${PREFIX}${id}.mdc`, {
137
+ body: `---\ndescription: Redline ${stack.title} rules\nglobs: ${stack.globs.join(',')}\n` +
138
+ `alwaysApply: false\n---\n\n${stackBody(ctx, id)}`,
139
+ });
140
+ }
141
+ return {
142
+ files,
143
+ prune: [{ dir: '.cursor/rules', matches: (f) => f.startsWith(PREFIX) && f.endsWith('.mdc') }],
144
+ };
145
+ };
146
+ // Claude skills: per-stack rules that load only when the stack is in play.
147
+ //
148
+ // The asymmetry this closes. Copilot receives .github/instructions/redline-*.md
149
+ // with applyTo globs — conditional, per-stack loading. Claude receives
150
+ // CLAUDE.md -> @AGENTS.md: the entire composed standard, every turn, for the life
151
+ // of every session. On a twelve-stack profile that is most of a context window
152
+ // spent on rules for languages the repository is not currently editing.
153
+ //
154
+ // Two constraints from the roadmap, both load-bearing:
155
+ //
156
+ // - Rules stay authored in standards/. This is packaging, not authoring, and no
157
+ // Claude-shaped concept may leak backward into how a rule is written. Every
158
+ // body below is the stack's own markdown, unmodified.
159
+ // - Build it thin. The roadmap rates this the highest-exposure piece in the
160
+ // plan — per-file conditional instruction loading is exactly what a platform
161
+ // makes free — so there is no cleverness here to maintain or to abandon.
162
+ //
163
+ // A skill loads on its description, not on a glob, so the description names the
164
+ // stack, its file extensions and its globs. That is the whole mechanism.
165
+ const skillDescription = (title, globs) => {
166
+ const extensions = [...new Set(globs.map((g) => g.slice(g.lastIndexOf('.'))).filter((e) => e.startsWith('.')))];
167
+ const suffix = extensions.length > 0 ? ` Covers ${extensions.join(', ')} files.` : '';
168
+ return (`Redline engineering standards for ${title}. Use when writing, editing or reviewing ` +
169
+ `${title} code in this repository — before proposing a change, not after.${suffix}`);
170
+ };
171
+ const skills = (ctx) => {
172
+ const files = new Map();
173
+ // Core always loads: it carries the output contract and the security floor,
174
+ // and it is not stack-scoped. Splitting it per stack would duplicate it twelve
175
+ // times and let a repository end up with none of it.
176
+ files.set(`.claude/skills/${PREFIX}core/SKILL.md`, {
177
+ localRules: true,
178
+ body: `---\nname: ${PREFIX}core\ndescription: >-\n Redline core engineering standards — the severity output contract, security,\n` +
179
+ ` type safety, error handling and scope discipline. Use when writing, editing or\n` +
180
+ ` reviewing any code in this repository.\n---\n\n` +
181
+ withLocal(ctx, `${header(ctx, ctx.stacks)}\n\n${read(ctx.root, ctx.manifest.core.source)}`),
182
+ });
183
+ for (const id of ctx.stacks) {
184
+ const stack = ctx.manifest.stacks[id];
185
+ files.set(`.claude/skills/${PREFIX}${id}/SKILL.md`, {
186
+ body: `---\nname: ${PREFIX}${id}\ndescription: >-\n ${skillDescription(stack.title, stack.globs)}\n---\n\n` +
187
+ `${header(ctx, [id])}\n\n${stackBody(ctx, id)}\n\n_Applies to: ${stack.globs.map((g) => `\`${g}\``).join(', ')}_`,
188
+ });
189
+ }
190
+ return {
191
+ files,
192
+ // A stack leaving the profile must take its skill with it, or a repository
193
+ // keeps loading rules for a language it no longer has. The directory shape
194
+ // means pruning matches on the directory name, not the file.
195
+ prune: [{ dir: '.claude/skills', matches: (f) => f.startsWith(PREFIX), directories: true }],
196
+ };
197
+ };
198
+ export const VENDORS = { copilot, agents, claude, cursor, skills };
199
+ //# sourceMappingURL=vendors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vendors.js","sourceRoot":"","sources":["../../cli/render/vendors.ts"],"names":[],"mappings":"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"}