@seanmars/tospec 0.19.0-beta.0 → 0.19.0-beta.2

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 (73) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +5 -2
  3. package/assets/metrics/app.js +22 -0
  4. package/assets/metrics/style.css +8 -0
  5. package/assets/rules/tospec/single-sourc-of-truth.md +9 -0
  6. package/dist/cli/index.d.ts.map +1 -1
  7. package/dist/cli/index.js +29 -4
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/commands/config.d.ts.map +1 -1
  10. package/dist/commands/config.js +5 -2
  11. package/dist/commands/config.js.map +1 -1
  12. package/dist/commands/dashboard.d.ts.map +1 -1
  13. package/dist/commands/dashboard.js +21 -5
  14. package/dist/commands/dashboard.js.map +1 -1
  15. package/dist/commands/metrics.d.ts +10 -1
  16. package/dist/commands/metrics.d.ts.map +1 -1
  17. package/dist/commands/metrics.js +9 -3
  18. package/dist/commands/metrics.js.map +1 -1
  19. package/dist/commands/shared-output.d.ts +17 -0
  20. package/dist/commands/shared-output.d.ts.map +1 -1
  21. package/dist/commands/shared-output.js +27 -2
  22. package/dist/commands/shared-output.js.map +1 -1
  23. package/dist/core/archive.d.ts.map +1 -1
  24. package/dist/core/archive.js +62 -29
  25. package/dist/core/archive.js.map +1 -1
  26. package/dist/core/artifact-graph/index.d.ts +1 -1
  27. package/dist/core/artifact-graph/index.d.ts.map +1 -1
  28. package/dist/core/artifact-graph/index.js +1 -1
  29. package/dist/core/artifact-graph/index.js.map +1 -1
  30. package/dist/core/artifact-graph/outputs.d.ts +10 -0
  31. package/dist/core/artifact-graph/outputs.d.ts.map +1 -1
  32. package/dist/core/artifact-graph/outputs.js +122 -2
  33. package/dist/core/artifact-graph/outputs.js.map +1 -1
  34. package/dist/core/dashboard-data.d.ts.map +1 -1
  35. package/dist/core/dashboard-data.js +42 -18
  36. package/dist/core/dashboard-data.js.map +1 -1
  37. package/dist/core/global-config.d.ts.map +1 -1
  38. package/dist/core/global-config.js +11 -1
  39. package/dist/core/global-config.js.map +1 -1
  40. package/dist/core/init.d.ts.map +1 -1
  41. package/dist/core/init.js +9 -5
  42. package/dist/core/init.js.map +1 -1
  43. package/dist/core/local-server.d.ts +14 -0
  44. package/dist/core/local-server.d.ts.map +1 -1
  45. package/dist/core/local-server.js +18 -0
  46. package/dist/core/local-server.js.map +1 -1
  47. package/dist/core/parsers/requirement-blocks.d.ts +14 -0
  48. package/dist/core/parsers/requirement-blocks.d.ts.map +1 -1
  49. package/dist/core/parsers/requirement-blocks.js +43 -18
  50. package/dist/core/parsers/requirement-blocks.js.map +1 -1
  51. package/dist/core/parsers/spec-structure.d.ts +1 -1
  52. package/dist/core/parsers/spec-structure.d.ts.map +1 -1
  53. package/dist/core/parsers/spec-structure.js +23 -0
  54. package/dist/core/parsers/spec-structure.js.map +1 -1
  55. package/dist/core/rules.d.ts +5 -0
  56. package/dist/core/rules.d.ts.map +1 -0
  57. package/dist/core/rules.js +22 -0
  58. package/dist/core/rules.js.map +1 -0
  59. package/dist/core/shared/rules-generation.d.ts +12 -4
  60. package/dist/core/shared/rules-generation.d.ts.map +1 -1
  61. package/dist/core/shared/rules-generation.js +68 -4
  62. package/dist/core/shared/rules-generation.js.map +1 -1
  63. package/dist/core/specs-apply.d.ts +2 -0
  64. package/dist/core/specs-apply.d.ts.map +1 -1
  65. package/dist/core/specs-apply.js +47 -5
  66. package/dist/core/specs-apply.js.map +1 -1
  67. package/dist/core/update.d.ts.map +1 -1
  68. package/dist/core/update.js +7 -5
  69. package/dist/core/update.js.map +1 -1
  70. package/dist/core/validation/validator.d.ts.map +1 -1
  71. package/dist/core/validation/validator.js +14 -0
  72. package/dist/core/validation/validator.js.map +1 -1
  73. package/package.json +1 -1
@@ -21,6 +21,24 @@ const ASSET_CONTENT_TYPES = {
21
21
  };
22
22
  /** Hosts considered loopback for binding and Host-header checks. */
23
23
  export const LOOPBACK_HOSTS = new Set(['127.0.0.1', 'localhost', '::1']);
24
+ /**
25
+ * The bind guard, in one place because it is the third trust boundary this
26
+ * module owns.
27
+ *
28
+ * It lived inline in `startDashboardServer`, so the metrics server — which takes
29
+ * the same `host`, goes through the same `listenFrom`, and shares
30
+ * `isAllowedHostHeader` and `serveAsset` from this module — had nothing to call
31
+ * and bound `0.0.0.0` without objecting. That is exactly the hole this file's
32
+ * header warns about: a guard with one implementation site cannot protect the
33
+ * second caller that never reaches it.
34
+ *
35
+ * `serverName` appears in the message so the refusal still names what refused.
36
+ */
37
+ export function assertBindableHost(host, serverName, allowRemote) {
38
+ if (LOOPBACK_HOSTS.has(host.toLowerCase()) || allowRemote)
39
+ return;
40
+ throw new Error(`Refusing to bind non-loopback host '${host}': the ${serverName} would be readable by anyone who can reach this machine. Pass --allow-remote to accept that risk.`);
41
+ }
24
42
  // -----------------------------------------------------------------------------
25
43
  // Responses
26
44
  // -----------------------------------------------------------------------------
@@ -1 +1 @@
1
- {"version":3,"file":"local-server.js","sourceRoot":"","sources":["../../src/core/local-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"local-server.js","sourceRoot":"","sources":["../../src/core/local-server.ts"],"names":[],"mappings":"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"}
@@ -38,6 +38,13 @@ export interface RenamedIssue {
38
38
  /** 1-based line number of the orphaned FROM:/TO: line. */
39
39
  line: number;
40
40
  }
41
+ /** A delta section header that appears more than once in one file. */
42
+ export interface DuplicateSection {
43
+ /** The header as authored at its first occurrence, e.g. '## ADDED Requirements'. */
44
+ title: string;
45
+ /** 1-based line numbers of every occurrence, in document order. */
46
+ lines: number[];
47
+ }
41
48
  export interface DeltaPlan {
42
49
  added: RequirementBlock[];
43
50
  modified: RequirementBlock[];
@@ -56,6 +63,13 @@ export interface DeltaPlan {
56
63
  }>;
57
64
  /** Orphaned FROM:/TO: lines that would otherwise be silently dropped. */
58
65
  renamedIssues: RenamedIssue[];
66
+ /**
67
+ * Delta section headers written more than once in this file. The parser no
68
+ * longer loses the repeated occurrences' content, but two identical headers
69
+ * are still almost always an editing accident, so the validator rejects them
70
+ * rather than guessing which one the author meant.
71
+ */
72
+ duplicateSections: DuplicateSection[];
59
73
  sectionPresence: {
60
74
  added: boolean;
61
75
  modified: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"requirement-blocks.d.ts","sourceRoot":"","sources":["../../../src/core/parsers/requirement-blocks.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAID;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,wBAAwB,CA+EpF;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,iBAAiB,GAAG,iBAAiB,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,6EAA6E;IAC7E,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B;;;;OAIG;IACH,aAAa,EAAE,gBAAgB,EAAE,CAAC;IAClC,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7C,yEAAyE;IACzE,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,eAAe,EAAE;QACf,KAAK,EAAE,OAAO,CAAC;QACf,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC;CACH;AAMD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CA6BzD"}
1
+ {"version":3,"file":"requirement-blocks.d.ts","sourceRoot":"","sources":["../../../src/core/parsers/requirement-blocks.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAID;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,wBAAwB,CA+EpF;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,iBAAiB,GAAG,iBAAiB,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;CACd;AAED,sEAAsE;AACtE,MAAM,WAAW,gBAAgB;IAC/B,oFAAoF;IACpF,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,6EAA6E;IAC7E,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B;;;;OAIG;IACH,aAAa,EAAE,gBAAgB,EAAE,CAAC;IAClC,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7C,yEAAyE;IACzE,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B;;;;;OAKG;IACH,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IACtC,eAAe,EAAE;QACf,KAAK,EAAE,OAAO,CAAC;QACf,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC;CACH;AAMD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAmCzD"}
@@ -97,15 +97,20 @@ export function parseDeltaSpec(content) {
97
97
  const lines = normalized.split('\n');
98
98
  const fenceMask = buildCodeFenceMask(lines);
99
99
  const sections = splitTopLevelSections(lines, fenceMask);
100
- const addedLookup = getSectionCaseInsensitive(sections, 'ADDED Requirements');
101
- const modifiedLookup = getSectionCaseInsensitive(sections, 'MODIFIED Requirements');
102
- const removedLookup = getSectionCaseInsensitive(sections, 'REMOVED Requirements');
103
- const renamedLookup = getSectionCaseInsensitive(sections, 'RENAMED Requirements');
104
- const added = parseRequirementBlocksFromSection(addedLookup.body);
105
- const modified = parseRequirementBlocksFromSection(modifiedLookup.body);
106
- const removedEntries = parseRemovedEntries(removedLookup.body);
107
- const removedBlocks = parseRequirementBlocksFromSection(removedLookup.body);
108
- const { pairs: renamedPairs, issues: renamedIssues } = parseRenamedPairs(renamedLookup.body);
100
+ const addedLookup = getSections(sections, 'ADDED Requirements');
101
+ const modifiedLookup = getSections(sections, 'MODIFIED Requirements');
102
+ const removedLookup = getSections(sections, 'REMOVED Requirements');
103
+ const renamedLookup = getSections(sections, 'RENAMED Requirements');
104
+ // Each occurrence is parsed on its own and the results concatenated, so a
105
+ // repeated section contributes all of its entries in document order without
106
+ // any entry being interpreted across the boundary between two occurrences.
107
+ const added = addedLookup.bodies.flatMap(parseRequirementBlocksFromSection);
108
+ const modified = modifiedLookup.bodies.flatMap(parseRequirementBlocksFromSection);
109
+ const removedEntries = removedLookup.bodies.flatMap(parseRemovedEntries);
110
+ const removedBlocks = removedLookup.bodies.flatMap(parseRequirementBlocksFromSection);
111
+ const renamedResults = renamedLookup.bodies.map(parseRenamedPairs);
112
+ const renamedPairs = renamedResults.flatMap((r) => r.pairs);
113
+ const renamedIssues = renamedResults.flatMap((r) => r.issues);
109
114
  return {
110
115
  added,
111
116
  modified,
@@ -114,6 +119,7 @@ export function parseDeltaSpec(content) {
114
119
  removedBlocks,
115
120
  renamed: renamedPairs,
116
121
  renamedIssues,
122
+ duplicateSections: findDuplicateSections(sections),
117
123
  sectionPresence: {
118
124
  added: addedLookup.found,
119
125
  modified: modifiedLookup.found,
@@ -122,9 +128,8 @@ export function parseDeltaSpec(content) {
122
128
  },
123
129
  };
124
130
  }
125
- const EMPTY_SECTION_BODY = { lines: [], fenceMask: [], offset: 0 };
126
131
  function splitTopLevelSections(lines, fenceMask) {
127
- const result = {};
132
+ const result = new Map();
128
133
  const indices = [];
129
134
  for (let i = 0; i < lines.length; i++) {
130
135
  if (fenceMask[i])
@@ -138,21 +143,41 @@ function splitTopLevelSections(lines, fenceMask) {
138
143
  const current = indices[i];
139
144
  const next = indices[i + 1];
140
145
  const end = next ? next.index : lines.length;
141
- result[current.title] = {
146
+ const body = {
147
+ title: current.title,
142
148
  lines: lines.slice(current.index + 1, end),
143
149
  fenceMask: fenceMask.slice(current.index + 1, end),
144
150
  offset: current.index + 1,
151
+ headerLine: current.index + 1,
145
152
  };
153
+ // Case-insensitive key: `getSections` matches case-insensitively, so two
154
+ // spellings that differ only in case are one section to every caller and
155
+ // must fold together here too.
156
+ const key = current.title.toLowerCase();
157
+ const existing = result.get(key);
158
+ if (existing)
159
+ existing.push(body);
160
+ else
161
+ result.set(key, [body]);
146
162
  }
147
163
  return result;
148
164
  }
149
- function getSectionCaseInsensitive(sections, desired) {
150
- const target = desired.toLowerCase();
151
- for (const [title, body] of Object.entries(sections)) {
152
- if (title.toLowerCase() === target)
153
- return { body, found: true };
165
+ function getSections(sections, desired) {
166
+ const bodies = sections.get(desired.toLowerCase());
167
+ return bodies ? { bodies, found: true } : { bodies: [], found: false };
168
+ }
169
+ /** Section titles that appear more than once, in document order. */
170
+ function findDuplicateSections(sections) {
171
+ const duplicates = [];
172
+ for (const bodies of sections.values()) {
173
+ if (bodies.length > 1) {
174
+ duplicates.push({
175
+ title: `## ${bodies[0].title}`,
176
+ lines: bodies.map((b) => b.headerLine),
177
+ });
178
+ }
154
179
  }
155
- return { body: EMPTY_SECTION_BODY, found: false };
180
+ return duplicates;
156
181
  }
157
182
  function parseRequirementBlocksFromSection(sectionBody) {
158
183
  const { lines, fenceMask } = sectionBody;
@@ -1 +1 @@
1
- {"version":3,"file":"requirement-blocks.js","sourceRoot":"","sources":["../../../src/core/parsers/requirement-blocks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"requirement-blocks.js","sourceRoot":"","sources":["../../../src/core/parsers/requirement-blocks.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  export interface MainSpecStructureIssue {
2
- kind: 'delta-header' | 'requirement-outside-requirements';
2
+ kind: 'delta-header' | 'requirement-outside-requirements' | 'duplicate-requirement';
3
3
  line: number;
4
4
  header: string;
5
5
  message: string;
@@ -1 +1 @@
1
- {"version":3,"file":"spec-structure.d.ts","sourceRoot":"","sources":["../../../src/core/parsers/spec-structure.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,cAAc,GAAG,kCAAkC,CAAC;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,sBAAsB,EAAE,CA6DrF;AAED,wBAAgB,oCAAoC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAI5E"}
1
+ {"version":3,"file":"spec-structure.d.ts","sourceRoot":"","sources":["../../../src/core/parsers/spec-structure.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,cAAc,GAAG,kCAAkC,GAAG,uBAAuB,CAAC;IACpF,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,sBAAsB,EAAE,CAqFrF;AAED,wBAAgB,oCAAoC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAI5E"}
@@ -1,4 +1,5 @@
1
1
  import { buildCodeFenceMask } from './requirement-text.js';
2
+ import { normalizeRequirementName } from './requirement-blocks.js';
2
3
  const REQUIREMENTS_SECTION_HEADER = /^##\s+Requirements\s*$/i;
3
4
  const TOP_LEVEL_SECTION_HEADER = /^##\s+/;
4
5
  const DELTA_HEADER = /^##\s+(ADDED|MODIFIED|REMOVED|RENAMED)\s+Requirements\s*$/i;
@@ -8,6 +9,10 @@ export function findMainSpecStructureIssues(content) {
8
9
  const stripped = stripFencedCodeBlocksPreservingLines(normalized);
9
10
  const lines = stripped.split('\n');
10
11
  const issues = [];
12
+ // Keyed the way buildUpdatedSpec keys its blocks. Any pair that would collide
13
+ // in that Map must be reported here, or this guard would pass a spec the merge
14
+ // still corrupts.
15
+ const firstSeenAt = new Map();
11
16
  const requirementsHeaderIndex = lines.findIndex(line => REQUIREMENTS_SECTION_HEADER.test(line));
12
17
  let requirementsEndIndex = lines.length;
13
18
  if (requirementsHeaderIndex !== -1) {
@@ -50,7 +55,25 @@ export function findMainSpecStructureIssues(content) {
50
55
  message: `Requirement header "${trimmed}" appears outside the main ## Requirements section. ` +
51
56
  'Main specs only parse requirements inside that section, so this requirement is currently invisible to validate, list, and archive.',
52
57
  });
58
+ continue;
59
+ }
60
+ // Duplicate names are only a merge hazard for requirements the merge sees,
61
+ // so this runs on the ones inside the section — the ones just reported as
62
+ // outside it are already fatal for a different reason.
63
+ const key = normalizeRequirementName(requirementMatch[1]);
64
+ const firstLine = firstSeenAt.get(key);
65
+ if (firstLine === undefined) {
66
+ firstSeenAt.set(key, i + 1);
67
+ continue;
53
68
  }
69
+ issues.push({
70
+ kind: 'duplicate-requirement',
71
+ line: i + 1,
72
+ header: trimmed,
73
+ message: `Requirement "${key}" is defined more than once (first at line ${firstLine}, again at line ${i + 1}). ` +
74
+ 'Merging a change into this spec keys requirements by name, so both copies would be replaced by the last one — ' +
75
+ 'the earlier body would be lost. Rename one or merge them.',
76
+ });
54
77
  }
55
78
  return issues;
56
79
  }
@@ -1 +1 @@
1
- {"version":3,"file":"spec-structure.js","sourceRoot":"","sources":["../../../src/core/parsers/spec-structure.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"spec-structure.js","sourceRoot":"","sources":["../../../src/core/parsers/spec-structure.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** Refresh only the workflow rule files of agents already configured for tospec. */
2
+ export declare class RulesCommand {
3
+ execute(targetPath: string): Promise<void>;
4
+ }
5
+ //# sourceMappingURL=rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/core/rules.ts"],"names":[],"mappings":"AAMA,oFAAoF;AACpF,qBAAa,YAAY;IACjB,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAajD"}
@@ -0,0 +1,22 @@
1
+ import path from 'node:path';
2
+ import { FileSystemUtils } from '../utils/file-system.js';
3
+ import { TOSPEC_DIR_NAME } from './config.js';
4
+ import { getConfiguredTools } from './shared/tool-detection.js';
5
+ import { planWorkflowRules, writeWorkflowRules } from './shared/rules-generation.js';
6
+ /** Refresh only the workflow rule files of agents already configured for tospec. */
7
+ export class RulesCommand {
8
+ async execute(targetPath) {
9
+ const projectPath = path.resolve(targetPath);
10
+ if (!await FileSystemUtils.directoryExists(path.join(projectPath, TOSPEC_DIR_NAME))) {
11
+ throw new Error("No Tospec directory found. Run 'tospec init' first.");
12
+ }
13
+ const tools = getConfiguredTools(projectPath);
14
+ if (tools.length === 0) {
15
+ console.log('No configured tools found. Run "tospec init" to set up tools.');
16
+ return;
17
+ }
18
+ const plan = await planWorkflowRules(projectPath, tools);
19
+ await writeWorkflowRules(plan);
20
+ }
21
+ }
22
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/core/rules.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAErF,oFAAoF;AACpF,MAAM,OAAO,YAAY;IACvB,KAAK,CAAC,OAAO,CAAC,UAAkB;QAC9B,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,eAAe,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC;YACpF,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,KAAK,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC;YAC7E,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QACzD,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;CACF"}
@@ -1,11 +1,19 @@
1
1
  /**
2
2
  * Rules Generation
3
3
  *
4
- * Writes static tospec rule files into an agent's `rules/` directory.
5
- * Unlike skills, rules are fixed, tospec-owned content, so there is no
6
- * canonical `.agents/` source-of-truth or hard-linking — a plain write into
7
- * each selected tool's dir is enough (init regenerates it on demand).
4
+ * Legacy decision rules retain their init-only writer. Workflow rules use a
5
+ * shipped Markdown template and a read-only plan before any project writes.
8
6
  */
9
7
  /** Write tospec rule files into `<projectPath>/<agentBaseDir>/rules/` for one tool. */
10
8
  export declare function writeToolRules(projectPath: string, agentBaseDir: string): Promise<void>;
9
+ export interface WorkflowRulePlan {
10
+ toolId: string;
11
+ destination: string;
12
+ content: string;
13
+ action: 'created' | 'updated' | 'unchanged';
14
+ }
15
+ /** Read every target before allowing any project mutation. */
16
+ export declare function planWorkflowRules(projectPath: string, toolIds: string[]): Promise<WorkflowRulePlan[]>;
17
+ /** Call only after the complete plan passed preflight. */
18
+ export declare function writeWorkflowRules(plan: WorkflowRulePlan[]): Promise<void>;
11
19
  //# sourceMappingURL=rules-generation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rules-generation.d.ts","sourceRoot":"","sources":["../../../src/core/shared/rules-generation.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAsBH,uFAAuF;AACvF,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK7F"}
1
+ {"version":3,"file":"rules-generation.d.ts","sourceRoot":"","sources":["../../../src/core/shared/rules-generation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAyBH,uFAAuF;AACvF,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK7F;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;CAC7C;AAwBD,8DAA8D;AAC9D,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA2B3G;AAED,0DAA0D;AAC1D,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhF"}
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * Rules Generation
3
3
  *
4
- * Writes static tospec rule files into an agent's `rules/` directory.
5
- * Unlike skills, rules are fixed, tospec-owned content, so there is no
6
- * canonical `.agents/` source-of-truth or hard-linking — a plain write into
7
- * each selected tool's dir is enough (init regenerates it on demand).
4
+ * Legacy decision rules retain their init-only writer. Workflow rules use a
5
+ * shipped Markdown template and a read-only plan before any project writes.
8
6
  */
9
7
  import path from 'node:path';
8
+ import { promises as fs } from 'node:fs';
9
+ import { createHash } from 'node:crypto';
10
+ import { AI_TOOLS } from '../config.js';
10
11
  import { FileSystemUtils } from '../../utils/file-system.js';
11
12
  // Trailing newline intentional.
12
13
  const DECISION_RULE = `# Decision
@@ -24,4 +25,67 @@ export async function writeToolRules(projectPath, agentBaseDir) {
24
25
  await FileSystemUtils.writeFile(dest, rule.content); // auto-creates parent dirs
25
26
  }
26
27
  }
28
+ const TEMPLATE_URL = new URL('../../../assets/rules/tospec/single-sourc-of-truth.md', import.meta.url);
29
+ const RULE_NAME = 'single-sourc-of-truth.md';
30
+ const END_MARKER = '<!-- /tospec:single-sourc-of-truth -->';
31
+ const MANAGED_DOCUMENT = /^<!-- tospec:single-sourc-of-truth:v1 sha256=([a-f0-9]{64}) -->\n([\s\S]*\n)<!-- \/tospec:single-sourc-of-truth -->\n$/;
32
+ function normalizeNewlines(content) {
33
+ return content.replace(/\r\n/g, '\n');
34
+ }
35
+ function bodyHash(body) {
36
+ return createHash('sha256').update(body, 'utf8').digest('hex');
37
+ }
38
+ function isIntactDocument(content) {
39
+ const match = MANAGED_DOCUMENT.exec(content);
40
+ // A dedicated file has exactly one frame; never silently drop text outside it.
41
+ return match !== null && match[0] === content
42
+ && !match[2].includes('<!-- tospec:single-sourc-of-truth:')
43
+ && !match[2].includes(END_MARKER)
44
+ && bodyHash(match[2]) === match[1];
45
+ }
46
+ /** Read every target before allowing any project mutation. */
47
+ export async function planWorkflowRules(projectPath, toolIds) {
48
+ if (toolIds.length === 0)
49
+ return [];
50
+ const body = normalizeNewlines(await fs.readFile(TEMPLATE_URL, 'utf8')).replace(/\n*$/, '\n');
51
+ const hash = bodyHash(body);
52
+ const content = `<!-- tospec:single-sourc-of-truth:v1 sha256=${hash} -->\n${body}${END_MARKER}\n`;
53
+ const plan = [];
54
+ const conflicts = [];
55
+ for (const toolId of toolIds) {
56
+ const tool = AI_TOOLS.find((tool) => tool.value === toolId);
57
+ if (!tool?.skillsDir)
58
+ throw new Error(`Unknown rule target: ${toolId}`);
59
+ const destination = path.join(projectPath, tool.skillsDir, 'rules', 'tospec', RULE_NAME);
60
+ let previous;
61
+ try {
62
+ previous = normalizeNewlines(await fs.readFile(destination, 'utf8'));
63
+ }
64
+ catch (error) {
65
+ if (error.code !== 'ENOENT')
66
+ throw error;
67
+ }
68
+ if (previous !== undefined && !isIntactDocument(previous)) {
69
+ conflicts.push(destination);
70
+ }
71
+ plan.push({ toolId, destination, content,
72
+ action: previous === undefined ? 'created' : previous === content ? 'unchanged' : 'updated' });
73
+ }
74
+ if (conflicts.length > 0) {
75
+ throw new Error(`Workflow rule conflict:\n${conflicts.join('\n')}\nPreserve your edits, remove the conflicting generated files, then rerun. Force does not bypass rule conflicts.`);
76
+ }
77
+ return plan;
78
+ }
79
+ /** Call only after the complete plan passed preflight. */
80
+ export async function writeWorkflowRules(plan) {
81
+ for (const entry of plan) {
82
+ if (entry.action !== 'unchanged') {
83
+ await FileSystemUtils.writeFile(entry.destination, entry.content);
84
+ }
85
+ console.log(`Rules ${entry.action}: ${entry.destination}`);
86
+ }
87
+ if (plan.some((entry) => entry.toolId === 'codex')) {
88
+ console.log('Codex: rule documents were generated; configure loading yourself. Markdown files in .codex/rules/ are not automatically loaded as instructions.');
89
+ }
90
+ }
27
91
  //# sourceMappingURL=rules-generation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rules-generation.js","sourceRoot":"","sources":["../../../src/core/shared/rules-generation.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,gCAAgC;AAChC,MAAM,aAAa,GAAG;;;CAGrB,CAAC;AAQF,uEAAuE;AACvE,MAAM,UAAU,GAAe;IAC7B,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE;CACxE,CAAC;AAEF,uFAAuF;AACvF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB,EAAE,YAAoB;IAC5E,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACzE,MAAM,eAAe,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,2BAA2B;IAClF,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"rules-generation.js","sourceRoot":"","sources":["../../../src/core/shared/rules-generation.ts"],"names":[],"mappings":"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"}
@@ -21,6 +21,7 @@ export declare function buildUpdatedSpec(update: SpecUpdate, changeName: string,
21
21
  silent?: boolean;
22
22
  }): Promise<{
23
23
  rebuilt: string;
24
+ crlf: boolean;
24
25
  retired: boolean;
25
26
  counts: {
26
27
  added: number;
@@ -40,6 +41,7 @@ export declare function writeUpdatedSpec(update: SpecUpdate, rebuilt: string, co
40
41
  }, options?: {
41
42
  silent?: boolean;
42
43
  displayPath?: string;
44
+ crlf?: boolean;
43
45
  }): Promise<void>;
44
46
  /**
45
47
  * Retire a capability the change emptied: delete its `spec.md`, then remove any
@@ -1 +1 @@
1
- {"version":3,"file":"specs-apply.d.ts","sourceRoot":"","sources":["../../src/core/specs-apply.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuBH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB;AAMD;;GAEG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAkDpG;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,CA8X/H;AAMD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAC7E,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACvD,OAAO,CAAC,IAAI,CAAC,CAcf;AA2BD;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACvD,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAOtG"}
1
+ {"version":3,"file":"specs-apply.d.ts","sourceRoot":"","sources":["../../src/core/specs-apply.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuBH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB;AAMD;;GAEG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAkDpG;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,CAyY9I;AAoCD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAC7E,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GACvE,OAAO,CAAC,IAAI,CAAC,CAkBf;AA2BD;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACvD,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAOtG"}
@@ -198,6 +198,15 @@ export async function buildUpdatedSpec(update, changeName, options = {}) {
198
198
  targetContent = buildSpecSkeleton(specName, changeName);
199
199
  }
200
200
  }
201
+ // Record the target's ending convention here, on the raw bytes, because
202
+ // everything downstream destroys it: extractRequirementsSection normalizes the
203
+ // document to LF before parsing, normalizeBlockRaw does it again per block,
204
+ // and the recompose joins with '\n'. Normalizing before parsing is correct —
205
+ // every structural regex below assumes LF — so the fix is to carry the
206
+ // convention forward, not to stop normalizing. A whole-file flag rather than
207
+ // per-line endings: a merged spec contains lines that had no original, so
208
+ // per-line fidelity is undefined for them.
209
+ const crlf = targetContent.includes('\r\n');
201
210
  const structureIssues = findMainSpecStructureIssues(targetContent);
202
211
  if (structureIssues.length > 0) {
203
212
  const details = structureIssues
@@ -380,13 +389,12 @@ export async function buildUpdatedSpec(update, changeName, options = {}) {
380
389
  // below, so every archive rewrote a well-formatted spec into that shape.
381
390
  // Separate non-empty slices with one blank line, and end the file with
382
391
  // exactly one newline instead of inheriting whatever `after` happened to hold.
383
- const rebuilt = [parts.before.trimEnd(), parts.headerLine, reqBody, parts.after.trim()]
392
+ const rebuilt = collapseBlankRunsOutsideFences([parts.before.trimEnd(), parts.headerLine, reqBody, parts.after.trim()]
384
393
  .filter((s) => s !== '')
385
- .join('\n\n')
386
- .replace(/\n{3,}/g, '\n\n')
387
- .trimEnd() + '\n';
394
+ .join('\n\n')).trimEnd() + '\n';
388
395
  return {
389
396
  rebuilt,
397
+ crlf,
390
398
  // The capability has no requirements left and this run is what emptied it.
391
399
  // Both halves matter. "No requirements left" alone would delete a spec on a
392
400
  // re-run of an already-synced REMOVED, taking with it any requirement added
@@ -406,6 +414,36 @@ export async function buildUpdatedSpec(update, changeName, options = {}) {
406
414
  function normalizeBlockRaw(raw) {
407
415
  return raw.replace(/\r\n?/g, '\n').trim();
408
416
  }
417
+ /**
418
+ * Collapse runs of blank lines to a single blank line, skipping fenced code.
419
+ *
420
+ * The collapse exists because the four slices joined above each carry their own
421
+ * boundary newlines, so the seams between them accumulate blank lines. Applied
422
+ * to the whole document as `replace(/\n{3,}/g, '\n\n')` it could not tell a seam
423
+ * from a blank line an author put inside a code sample deliberately, so every
424
+ * archive quietly edited the examples in a spec. The seams are all outside any
425
+ * fence by construction, so masking fenced lines loses nothing the collapse was
426
+ * written for.
427
+ */
428
+ function collapseBlankRunsOutsideFences(content) {
429
+ const lines = content.split('\n');
430
+ const mask = buildCodeFenceMask(lines);
431
+ const kept = [];
432
+ const keptMask = [];
433
+ for (let i = 0; i < lines.length; i++) {
434
+ if (!mask[i] && lines[i].trim() === '') {
435
+ const last = kept.length - 1;
436
+ // Drop this blank only if the previous kept line is a blank that was also
437
+ // outside a fence — a blank line inside a fence is content, and it must
438
+ // not license dropping the one that follows it.
439
+ if (last >= 0 && !keptMask[last] && kept[last].trim() === '')
440
+ continue;
441
+ }
442
+ kept.push(lines[i]);
443
+ keptMask.push(mask[i]);
444
+ }
445
+ return kept.join('\n');
446
+ }
409
447
  /**
410
448
  * Write an updated spec to disk.
411
449
  */
@@ -413,7 +451,11 @@ export async function writeUpdatedSpec(update, rebuilt, counts, options = {}) {
413
451
  // Create target directory if needed
414
452
  const targetDir = path.dirname(update.target);
415
453
  await fs.mkdir(targetDir, { recursive: true });
416
- await fs.writeFile(update.target, rebuilt);
454
+ // `rebuilt` is pure LF by construction; restore the convention the target had
455
+ // before the merge so archiving a CRLF spec does not produce a whole-file diff
456
+ // on Windows. A brand new spec has no prior convention and stays LF.
457
+ const content = options.crlf ? rebuilt.replace(/\r?\n/g, '\r\n') : rebuilt;
458
+ await fs.writeFile(update.target, content);
417
459
  if (options.silent)
418
460
  return;
419
461
  const specName = path.basename(path.dirname(update.target));