@rsaglobaltech/specgate 0.27.9 → 1.0.0-rc.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 (136) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/packages/core/src/application/ValidateChangeUseCase.js +19 -3
  3. package/dist/packages/core/src/application/ValidateChangeUseCase.js.map +1 -1
  4. package/dist/packages/core/src/domain/ApiContract.js +157 -0
  5. package/dist/packages/core/src/domain/ApiContract.js.map +1 -0
  6. package/dist/packages/core/src/domain/Approvals.js +127 -0
  7. package/dist/packages/core/src/domain/Approvals.js.map +1 -0
  8. package/dist/packages/core/src/domain/ChangeLayers.js +281 -0
  9. package/dist/packages/core/src/domain/ChangeLayers.js.map +1 -0
  10. package/dist/packages/core/src/domain/HarnessConfig.js.map +1 -1
  11. package/dist/packages/core/src/domain/HarnessGaps.js +182 -0
  12. package/dist/packages/core/src/domain/HarnessGaps.js.map +1 -0
  13. package/dist/packages/core/src/domain/HarnessReport.js +16 -1
  14. package/dist/packages/core/src/domain/HarnessReport.js.map +1 -1
  15. package/dist/packages/core/src/domain/HarnessRun.js.map +1 -1
  16. package/dist/packages/core/src/domain/Principles.js +119 -0
  17. package/dist/packages/core/src/domain/Principles.js.map +1 -0
  18. package/dist/packages/core/src/domain/RequirementGraph.js +12 -1
  19. package/dist/packages/core/src/domain/RequirementGraph.js.map +1 -1
  20. package/dist/packages/core/src/domain/Workspace.js +150 -0
  21. package/dist/packages/core/src/domain/Workspace.js.map +1 -0
  22. package/dist/packages/core/src/index.js +1 -0
  23. package/dist/packages/core/src/index.js.map +1 -1
  24. package/dist/packages/core/src/infrastructure/HarnessConfigFile.js +12 -0
  25. package/dist/packages/core/src/infrastructure/HarnessConfigFile.js.map +1 -1
  26. package/dist/packages/mcp-spec-driven/src/tools.js +18 -0
  27. package/dist/packages/mcp-spec-driven/src/tools.js.map +1 -1
  28. package/dist/scripts/alm/cli.js +45 -4
  29. package/dist/scripts/alm/cli.js.map +1 -1
  30. package/dist/scripts/alm/clients.js +3 -1
  31. package/dist/scripts/alm/clients.js.map +1 -1
  32. package/dist/scripts/alm/phases.js +279 -0
  33. package/dist/scripts/alm/phases.js.map +1 -0
  34. package/dist/scripts/alm/port.js +33 -5
  35. package/dist/scripts/alm/port.js.map +1 -1
  36. package/dist/scripts/alm/providers/azure.js +72 -11
  37. package/dist/scripts/alm/providers/azure.js.map +1 -1
  38. package/dist/scripts/alm/providers/github.js +67 -7
  39. package/dist/scripts/alm/providers/github.js.map +1 -1
  40. package/dist/scripts/alm/providers/index.js +8 -2
  41. package/dist/scripts/alm/providers/index.js.map +1 -1
  42. package/dist/scripts/alm/providers/jira.js +86 -8
  43. package/dist/scripts/alm/providers/jira.js.map +1 -1
  44. package/dist/scripts/alm/providers/linear.js +167 -0
  45. package/dist/scripts/alm/providers/linear.js.map +1 -0
  46. package/dist/scripts/change/artifacts.js +15 -1
  47. package/dist/scripts/change/artifacts.js.map +1 -1
  48. package/dist/scripts/change/instructions.js +39 -5
  49. package/dist/scripts/change/instructions.js.map +1 -1
  50. package/dist/scripts/cli/commands/alm/PhaseCommand.js +153 -0
  51. package/dist/scripts/cli/commands/alm/PhaseCommand.js.map +1 -0
  52. package/dist/scripts/cli/commands/alm/PullCommand.js +33 -2
  53. package/dist/scripts/cli/commands/alm/PullCommand.js.map +1 -1
  54. package/dist/scripts/cli/commands/alm/pull-back.js +104 -0
  55. package/dist/scripts/cli/commands/alm/pull-back.js.map +1 -0
  56. package/dist/scripts/cli/commands/change/ChangeCommand.js +92 -14
  57. package/dist/scripts/cli/commands/change/ChangeCommand.js.map +1 -1
  58. package/dist/scripts/cli/commands/change/TicketCommand.js +20 -7
  59. package/dist/scripts/cli/commands/change/TicketCommand.js.map +1 -1
  60. package/dist/scripts/cli/commands/harness/RunCommand.js +64 -20
  61. package/dist/scripts/cli/commands/harness/RunCommand.js.map +1 -1
  62. package/dist/scripts/cli/commands/project/AdoptCommand.js +44 -4
  63. package/dist/scripts/cli/commands/project/AdoptCommand.js.map +1 -1
  64. package/dist/scripts/cli/commands/project/MigrateCommand.js +166 -0
  65. package/dist/scripts/cli/commands/project/MigrateCommand.js.map +1 -0
  66. package/dist/scripts/cli/commands/project/OnboardCommand.js +23 -5
  67. package/dist/scripts/cli/commands/project/OnboardCommand.js.map +1 -1
  68. package/dist/scripts/cli/commands/quality/CheckCommand.js +25 -0
  69. package/dist/scripts/cli/commands/quality/CheckCommand.js.map +1 -1
  70. package/dist/scripts/cli/commands/quality/ValidateSpecsCommand.js +15 -0
  71. package/dist/scripts/cli/commands/quality/ValidateSpecsCommand.js.map +1 -1
  72. package/dist/scripts/cli/commands/spec/ContractCommand.js +117 -0
  73. package/dist/scripts/cli/commands/spec/ContractCommand.js.map +1 -0
  74. package/dist/scripts/cli/commands/spec/DraftCommand.js +22 -8
  75. package/dist/scripts/cli/commands/spec/DraftCommand.js.map +1 -1
  76. package/dist/scripts/cli/commands/spec/DriftCommand.js +128 -0
  77. package/dist/scripts/cli/commands/spec/DriftCommand.js.map +1 -0
  78. package/dist/scripts/cli/commands/spec/StatusCommand.js +12 -0
  79. package/dist/scripts/cli/commands/spec/StatusCommand.js.map +1 -1
  80. package/dist/scripts/cli/commands/spec/StudioCommand.js +43 -1
  81. package/dist/scripts/cli/commands/spec/StudioCommand.js.map +1 -1
  82. package/dist/scripts/cli/commands/workspace/WorkspaceCommand.js +485 -0
  83. package/dist/scripts/cli/commands/workspace/WorkspaceCommand.js.map +1 -0
  84. package/dist/scripts/contract.js +10 -0
  85. package/dist/scripts/contract.js.map +1 -0
  86. package/dist/scripts/docs/nav.js +16 -1
  87. package/dist/scripts/docs/nav.js.map +1 -1
  88. package/dist/scripts/draft/drafting-guide.js +6 -0
  89. package/dist/scripts/draft/drafting-guide.js.map +1 -1
  90. package/dist/scripts/draft/ticket-guide.js +5 -0
  91. package/dist/scripts/draft/ticket-guide.js.map +1 -1
  92. package/dist/scripts/drift.js +10 -0
  93. package/dist/scripts/drift.js.map +1 -0
  94. package/dist/scripts/harness/gap-evidence.js +149 -0
  95. package/dist/scripts/harness/gap-evidence.js.map +1 -0
  96. package/dist/scripts/harness/prompt.js +5 -1
  97. package/dist/scripts/harness/prompt.js.map +1 -1
  98. package/dist/scripts/harness/report.js +104 -5
  99. package/dist/scripts/harness/report.js.map +1 -1
  100. package/dist/scripts/lib/approvals.js +243 -0
  101. package/dist/scripts/lib/approvals.js.map +1 -0
  102. package/dist/scripts/lib/change-review.js +19 -11
  103. package/dist/scripts/lib/change-review.js.map +1 -1
  104. package/dist/scripts/lib/contracts.js +211 -0
  105. package/dist/scripts/lib/contracts.js.map +1 -0
  106. package/dist/scripts/lib/drift.js +80 -0
  107. package/dist/scripts/lib/drift.js.map +1 -0
  108. package/dist/scripts/lib/live-model.js +1 -0
  109. package/dist/scripts/lib/live-model.js.map +1 -1
  110. package/dist/scripts/lib/migrate.js +264 -0
  111. package/dist/scripts/lib/migrate.js.map +1 -0
  112. package/dist/scripts/lib/role-packages.js +230 -0
  113. package/dist/scripts/lib/role-packages.js.map +1 -0
  114. package/dist/scripts/lib/steering.js +180 -0
  115. package/dist/scripts/lib/steering.js.map +1 -0
  116. package/dist/scripts/lib/studio-app-page.js +28 -5
  117. package/dist/scripts/lib/studio-app-page.js.map +1 -1
  118. package/dist/scripts/lib/studio-app.js +29 -0
  119. package/dist/scripts/lib/studio-app.js.map +1 -1
  120. package/dist/scripts/lib/studio-route.js +20 -0
  121. package/dist/scripts/lib/studio-route.js.map +1 -1
  122. package/dist/scripts/lib/surface.js +55 -0
  123. package/dist/scripts/lib/surface.js.map +1 -1
  124. package/dist/scripts/lib/workspace-live-page.js +90 -0
  125. package/dist/scripts/lib/workspace-live-page.js.map +1 -0
  126. package/dist/scripts/lib/workspace-live.js +216 -0
  127. package/dist/scripts/lib/workspace-live.js.map +1 -0
  128. package/dist/scripts/lib/workspace.js +406 -0
  129. package/dist/scripts/lib/workspace.js.map +1 -0
  130. package/dist/scripts/migrate.js +10 -0
  131. package/dist/scripts/migrate.js.map +1 -0
  132. package/dist/scripts/schema/registry.js +12 -0
  133. package/dist/scripts/schema/registry.js.map +1 -1
  134. package/dist/scripts/workspace.js +10 -0
  135. package/dist/scripts/workspace.js.map +1 -0
  136. package/package.json +1 -1
@@ -0,0 +1,243 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.APPROVALS_FILE = void 0;
37
+ exports.approvalSettings = approvalSettings;
38
+ exports.gitIdentity = gitIdentity;
39
+ exports.changeSchema = changeSchema;
40
+ exports.readRecords = readRecords;
41
+ exports.changeApprovals = changeApprovals;
42
+ exports.approveLayers = approveLayers;
43
+ exports.missingApprovals = missingApprovals;
44
+ const fs = __importStar(require("node:fs"));
45
+ const path = __importStar(require("node:path"));
46
+ const node_child_process_1 = require("node:child_process");
47
+ const YamlLite_1 = require("../../packages/core/src/domain/YamlLite");
48
+ const ChangeLayers_1 = require("../../packages/core/src/domain/ChangeLayers");
49
+ const Approvals_1 = require("../../packages/core/src/domain/Approvals");
50
+ /**
51
+ * The project side of roles and approvals (REQ-310..315, ADR-0043): the
52
+ * settings in `harness.config.yaml`, the git identity of whoever approves, and
53
+ * `approvals.json` in the change folder — which moves to the archive with it.
54
+ */
55
+ exports.APPROVALS_FILE = "approvals.json";
56
+ const changeDir = (projectDir, id) => path.join(projectDir, "docs", "specs", "changes", id);
57
+ function read(file) {
58
+ try {
59
+ return fs.readFileSync(file, "utf8");
60
+ }
61
+ catch {
62
+ return null;
63
+ }
64
+ }
65
+ /** `roles:` and `approvals:` of `harness.config.yaml`; the defaults without one. */
66
+ function approvalSettings(projectDir) {
67
+ const text = read(path.join(projectDir, "harness.config.yaml"));
68
+ const parsed = text ? (0, YamlLite_1.parseYamlLite)(text) : {};
69
+ return (0, Approvals_1.readApprovalSettings)(parsed && typeof parsed === "object" && !Array.isArray(parsed)
70
+ ? parsed
71
+ : {});
72
+ }
73
+ /** Who runs the command, as git knows them in this project. */
74
+ function gitIdentity(projectDir) {
75
+ const get = (key) => ((0, node_child_process_1.spawnSync)("git", ["config", key], { cwd: projectDir, encoding: "utf8" }).stdout || "").trim();
76
+ return { name: get("user.name"), email: get("user.email") };
77
+ }
78
+ /** The change's schema: `layered` from 1.0 on, `spec-driven` for a 0.27 change. */
79
+ function changeSchema(projectDir, id) {
80
+ const yaml = read(path.join(changeDir(projectDir, id), "change.yaml")) || "";
81
+ return (/^schema:\s*(\S+)/m.exec(yaml) || [])[1] || "spec-driven";
82
+ }
83
+ /** Each layer and its text, or null when it is missing or still as scaffolded. */
84
+ function layerTexts(projectDir, id) {
85
+ const dir = changeDir(projectDir, id);
86
+ return ChangeLayers_1.LAYERS.map((l) => {
87
+ const file = l.id === "discover" && !fs.existsSync(path.join(dir, l.file)) ? ChangeLayers_1.LEGACY_DISCOVER : l.file;
88
+ const text = read(path.join(dir, file));
89
+ const written = text !== null && !(0, ChangeLayers_1.isUntouchedLayer)(l.id, text, id);
90
+ return { id: l.id, owner: l.owner, file, text: written ? text : null };
91
+ });
92
+ }
93
+ function readRecords(projectDir, id) {
94
+ const text = read(path.join(changeDir(projectDir, id), exports.APPROVALS_FILE));
95
+ if (!text)
96
+ return [];
97
+ try {
98
+ const parsed = JSON.parse(text);
99
+ return Array.isArray(parsed) ? parsed : [];
100
+ }
101
+ catch {
102
+ return [];
103
+ }
104
+ }
105
+ function changeApprovals(projectDir, id) {
106
+ const settings = approvalSettings(projectDir);
107
+ const records = readRecords(projectDir, id);
108
+ const layers = (0, Approvals_1.layerApprovals)(layerTexts(projectDir, id), records, settings);
109
+ const schema = changeSchema(projectDir, id);
110
+ // A change with none of its layers written — a delta and nothing else — is
111
+ // approved as 0.27 approved it: by the `approved:` line `change approve` writes.
112
+ const line = approvedLine(projectDir, id);
113
+ const anyWritten = layers.some((l) => l.present);
114
+ const approved = anyWritten ? (0, Approvals_1.changeApproved)(layers) : Boolean(line);
115
+ const dates = layers.flatMap((l) => l.approvals.map((a) => a.at)).sort();
116
+ return {
117
+ change: id,
118
+ schema,
119
+ required: (0, Approvals_1.approvalsRequired)(schema, settings),
120
+ layers,
121
+ approved,
122
+ approvedAt: !approved ? "" : anyWritten ? dates[dates.length - 1] || "" : line,
123
+ recorded: records.length > 0,
124
+ };
125
+ }
126
+ /** The date on the `approved:` line of `change.yaml`, or "". */
127
+ function approvedLine(projectDir, id) {
128
+ const yaml = read(path.join(changeDir(projectDir, id), "change.yaml")) || "";
129
+ return (/^approved:\s*(\S+)/m.exec(yaml) || [])[1] || "";
130
+ }
131
+ /** Keep `approved:` in `change.yaml` in step with the approvals: written once all are in. */
132
+ function syncApprovedLine(projectDir, id, date) {
133
+ const file = path.join(changeDir(projectDir, id), "change.yaml");
134
+ const yaml = read(file) || "";
135
+ const without = yaml.replace(/^approved:.*\n?/m, "");
136
+ const next = date ? `${without.replace(/\n*$/, "\n")}approved: ${date}\n` : without;
137
+ if (next !== yaml)
138
+ fs.writeFileSync(file, next, "utf8");
139
+ }
140
+ /**
141
+ * Record the person's approval of the given layers — or, with `null`, of every
142
+ * written layer they own (REQ-311). Refuses a layer that is not written or
143
+ * whose owning role the person does not hold, naming the role and its people.
144
+ */
145
+ function approveLayers(projectDir, id, layers, today, who = gitIdentity(projectDir)) {
146
+ if (!fs.existsSync(changeDir(projectDir, id))) {
147
+ return { ok: false, code: "change_not_found", message: `No open change ${id}.` };
148
+ }
149
+ const settings = approvalSettings(projectDir);
150
+ const texts = layerTexts(projectDir, id);
151
+ const present = texts.filter((t) => t.text !== null);
152
+ const person = who.email || who.name || "this git identity";
153
+ const ownerOf = (owner) => {
154
+ const people = settings.roles[owner] || [];
155
+ return `the ${owner} role${people.length ? ` (${people.join(", ")})` : ""}`;
156
+ };
157
+ let targets;
158
+ if (layers) {
159
+ targets = [];
160
+ for (const l of layers) {
161
+ const t = texts.find((x) => x.id === l);
162
+ if (!t) {
163
+ return {
164
+ ok: false,
165
+ code: "approve_unknown_layer",
166
+ message: `${l} is not a layer: discover, design or tasks.`,
167
+ };
168
+ }
169
+ if (t.text === null) {
170
+ return {
171
+ ok: false,
172
+ code: "approve_layer_missing",
173
+ message: `${id} has no ${t.file} written yet: there is nothing of the ${l} to approve.`,
174
+ fix: `Write ${t.file}, then approve it.`,
175
+ };
176
+ }
177
+ if (!(0, Approvals_1.holdsRole)(settings, t.owner, who)) {
178
+ return {
179
+ ok: false,
180
+ code: "approve_not_owner",
181
+ message: `${person} cannot approve the ${l} of ${id}: it belongs to ${ownerOf(t.owner)}.`,
182
+ fix: `Have someone in the ${t.owner} role run specgate change approve ${id} --layer ${l}, or name ${person} under roles.${t.owner} in harness.config.yaml.`,
183
+ };
184
+ }
185
+ targets.push(t);
186
+ }
187
+ }
188
+ else {
189
+ targets = present.filter((t) => (0, Approvals_1.holdsRole)(settings, t.owner, who));
190
+ if (present.length > 0 && targets.length === 0) {
191
+ return {
192
+ ok: false,
193
+ code: "approve_not_owner",
194
+ message: `${person} holds none of the roles that own the layers of ${id}: ${present
195
+ .map((t) => `${t.id} → ${t.owner}`)
196
+ .join(", ")}.`,
197
+ fix: "Name them under roles: in harness.config.yaml, or have the owners approve.",
198
+ };
199
+ }
200
+ }
201
+ const records = readRecords(projectDir, id);
202
+ for (const t of targets) {
203
+ const hash = (0, Approvals_1.contentHash)(t.text);
204
+ const key = (who.email || who.name).toLowerCase();
205
+ const already = records.some((r) => r.layer === t.id && r.hash === hash && (r.by.email || r.by.name).toLowerCase() === key);
206
+ if (!already)
207
+ records.push({ layer: t.id, by: who, role: t.owner, hash, at: today });
208
+ }
209
+ if (targets.length > 0) {
210
+ fs.writeFileSync(path.join(changeDir(projectDir, id), exports.APPROVALS_FILE), `${JSON.stringify(records, null, 2)}\n`, "utf8");
211
+ }
212
+ const after = changeApprovals(projectDir, id);
213
+ // A 0.27 change with none of the layers written is approved as 0.27 did it.
214
+ const date = present.length === 0 ? today : after.approvedAt;
215
+ syncApprovedLine(projectDir, id, date);
216
+ return {
217
+ ok: true,
218
+ change: id,
219
+ approved: date,
220
+ layers: targets.map((t) => t.id),
221
+ pending: after.layers.filter((l) => l.present && !l.approved).map((l) => l.layer),
222
+ };
223
+ }
224
+ /** Why the harness must not build the change yet, or null when it may (REQ-315). */
225
+ function missingApprovals(projectDir, id) {
226
+ const state = changeApprovals(projectDir, id);
227
+ if (!state.required || state.approved)
228
+ return null;
229
+ const waiting = state.layers.filter((l) => l.present && !l.approved);
230
+ const what = waiting.length
231
+ ? waiting
232
+ .map((l) => `${l.layer} (${l.approvals.length} of ${l.quorum} approval(s), by the ${l.owner} role)`)
233
+ .join(", ")
234
+ : "nobody approved it";
235
+ const layer = waiting[0];
236
+ return {
237
+ message: `${id} is not approved: ${what}.`,
238
+ fix: layer
239
+ ? `specgate change approve ${id} --layer ${layer.layer}, by the ${layer.owner} role — or approvals: { required: never } in harness.config.yaml for the 0.27 behaviour.`
240
+ : `specgate change approve ${id} — or approvals: { required: never } in harness.config.yaml for the 0.27 behaviour.`,
241
+ };
242
+ }
243
+ //# sourceMappingURL=approvals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../../scripts/lib/approvals.ts"],"names":[],"mappings":"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"}
@@ -42,6 +42,7 @@ const fs = __importStar(require("node:fs"));
42
42
  const path = __importStar(require("node:path"));
43
43
  const Clarification_1 = require("../../packages/core/src/domain/Clarification");
44
44
  const DraftCommand_1 = require("../cli/commands/spec/DraftCommand");
45
+ const approvals_1 = require("./approvals");
45
46
  /**
46
47
  * A person's review of a draft change (REQ-206, REQ-207): approving it, which
47
48
  * Build waits for, and asking for a change in their own words.
@@ -58,10 +59,19 @@ function read(file) {
58
59
  return undefined;
59
60
  }
60
61
  }
61
- /** When a person approved the change, or "" when nobody has. */
62
+ /**
63
+ * When the change was approved, or "" while it is not. A 1.0 change, and any
64
+ * change with recorded approvals, is approved only while every written layer's
65
+ * approvals match its text (REQ-314); a 0.27 change without any reads the
66
+ * `approved:` line it always had.
67
+ */
62
68
  function approvedOn(projectDir, id) {
63
69
  const yaml = read(path.join(changeDir(projectDir, id), "change.yaml")) || "";
64
- return (/^approved:\s*(\S+)/m.exec(yaml) || [])[1] || "";
70
+ const line = (/^approved:\s*(\S+)/m.exec(yaml) || [])[1] || "";
71
+ const state = (0, approvals_1.changeApprovals)(projectDir, id);
72
+ if (state.schema === "layered" || state.recorded)
73
+ return state.approved ? state.approvedAt : "";
74
+ return line;
65
75
  }
66
76
  /** What stops a change from being approved: checklist errors and open questions. */
67
77
  function approvalBlockers(projectDir, id) {
@@ -84,9 +94,12 @@ function approvalBlockers(projectDir, id) {
84
94
  }
85
95
  return out;
86
96
  }
87
- /** Record that a person approved the change (REQ-206). */
88
- function approveChange(projectDir, id, today) {
89
- const file = path.join(changeDir(projectDir, id), "change.yaml");
97
+ /**
98
+ * Record that a person approved the change (REQ-206): the layers they own, or
99
+ * the one named (REQ-311). `approved` is the date once every layer is in, ""
100
+ * while some still wait.
101
+ */
102
+ function approveChange(projectDir, id, today, layer) {
90
103
  if (!fs.existsSync(changeDir(projectDir, id))) {
91
104
  return { ok: false, code: "change_not_found", message: `No open change ${id}.` };
92
105
  }
@@ -99,12 +112,7 @@ function approveChange(projectDir, id, today) {
99
112
  blockers,
100
113
  };
101
114
  }
102
- const yaml = read(file) || "";
103
- const next = /^approved:/m.test(yaml)
104
- ? yaml.replace(/^approved:.*$/m, `approved: ${today}`)
105
- : `${yaml.replace(/\n*$/, "\n")}approved: ${today}\n`;
106
- fs.writeFileSync(file, next, "utf8");
107
- return { ok: true, change: id, approved: today };
115
+ return (0, approvals_1.approveLayers)(projectDir, id, layer ? [layer] : null, today);
108
116
  }
109
117
  const NOTES_HEADER = "| Date | Requirement | Request |";
110
118
  function cell(text) {
@@ -1 +1 @@
1
- {"version":3,"file":"change-review.js","sourceRoot":"","sources":["../../../scripts/lib/change-review.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"change-review.js","sourceRoot":"","sources":["../../../scripts/lib/change-review.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,gCAMC;AAQD,4CAiBC;AAWD,sCAmBC;AAeD,kCAgBC;AAGD,gCAkBC;AAjJD,4CAA8B;AAC9B,gDAAkC;AAClC,gFAA6E;AAC7E,oEAAgE;AAEhE,2CAA6D;AAE7D;;;GAGG;AAEH,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;AAEtD,SAAS,SAAS,CAAC,UAAkB,EAAE,EAAU;IAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,IAAI,CAAC,IAAY;IACxB,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,UAAU,CAAC,UAAkB,EAAE,EAAU;IACvD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7E,MAAM,IAAI,GAAG,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/D,MAAM,KAAK,GAAG,IAAA,2BAAe,EAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC9C,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IAChG,OAAO,IAAI,CAAC;AACd,CAAC;AAOD,oFAAoF;AACpF,SAAgB,gBAAgB,CAAC,UAAkB,EAAE,EAAU;IAC7D,MAAM,GAAG,GAAc,EAAE,CAAC;IAC1B,MAAM,CAAC,GAAG,IAAA,0BAAW,EAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACtC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;QACnB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACjE,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YAChC,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO;gBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC;IAC7E,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,IAAA,6BAAa,EAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC1D,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAMD;;;;GAIG;AACH,SAAgB,aAAa,CAC3B,UAAkB,EAClB,EAAU,EACV,KAAa,EACb,KAAe;IAEf,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;QAC9C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC;IACnF,CAAC;IACD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAClD,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,GAAG,EAAE,4BAA4B,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACrF,QAAQ;SACT,CAAC;IACJ,CAAC;IACD,OAAO,IAAA,yBAAa,EAAC,UAAU,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACtE,CAAC;AAQD,MAAM,YAAY,GAAG,kCAAkC,CAAC;AAExD,SAAS,IAAI,CAAC,IAAY;IACxB,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACxE,CAAC;AAED,iCAAiC;AACjC,SAAgB,WAAW,CAAC,UAAkB,EAAE,EAAU;IACxD,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC;IACzE,OAAO,EAAE;SACN,KAAK,CAAC,OAAO,CAAC;SACd,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,8BAA8B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SACrD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,CAAC,GAAG,CAAC;aACR,KAAK,CAAC,WAAW,CAAC;aAClB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;aACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACxB,OAAO;YACL,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACV,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACrC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACzC,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC;AAED,8DAA8D;AAC9D,SAAgB,UAAU,CACxB,UAAkB,EAClB,EAAU,EACV,IAAY,EACZ,WAAmB,EACnB,KAAa;IAEb,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;QAC9C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC;IACnF,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC;IAC7F,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC;IAC/D,MAAM,EAAE,GACN,IAAI,CAAC,IAAI,CAAC;QACV,cAAc,EAAE,gEAAgE,YAAY,mBAAmB,CAAC;IAClH,MAAM,GAAG,GAAG,KAAK,KAAK,MAAM,WAAW,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACnE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IACtE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,WAAW,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AAC7E,CAAC"}
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ /**
3
+ * The project's interface contracts and the requirements that cite them
4
+ * (REQ-335, REQ-336).
5
+ *
6
+ * A contract is an OpenAPI or AsyncAPI document anywhere in the project, or
7
+ * any file an `api=` reference names. A reference is read off the
8
+ * `specgate:trace` comment of a requirement in spec.md or a capability spec.
9
+ */
10
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ var desc = Object.getOwnPropertyDescriptor(m, k);
13
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
+ desc = { enumerable: true, get: function() { return m[k]; } };
15
+ }
16
+ Object.defineProperty(o, k2, desc);
17
+ }) : (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ o[k2] = m[k];
20
+ }));
21
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
23
+ }) : function(o, v) {
24
+ o["default"] = v;
25
+ });
26
+ var __importStar = (this && this.__importStar) || (function () {
27
+ var ownKeys = function(o) {
28
+ ownKeys = Object.getOwnPropertyNames || function (o) {
29
+ var ar = [];
30
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
+ return ar;
32
+ };
33
+ return ownKeys(o);
34
+ };
35
+ return function (mod) {
36
+ if (mod && mod.__esModule) return mod;
37
+ var result = {};
38
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
+ __setModuleDefault(result, mod);
40
+ return result;
41
+ };
42
+ })();
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.apiCitations = apiCitations;
45
+ exports.projectContracts = projectContracts;
46
+ exports.apiReferenceProblems = apiReferenceProblems;
47
+ exports.contractReport = contractReport;
48
+ const fs = __importStar(require("node:fs"));
49
+ const path = __importStar(require("node:path"));
50
+ const ApiContract_1 = require("../../packages/core/src/domain/ApiContract");
51
+ const SpecParser_1 = require("../../packages/core/src/domain/SpecParser");
52
+ const ChangeWorkspace_1 = require("../../packages/core/src/infrastructure/ChangeWorkspace");
53
+ const diagnostics_1 = require("./diagnostics");
54
+ const SKIP = new Set([
55
+ ".git",
56
+ "node_modules",
57
+ "dist",
58
+ "target",
59
+ "build",
60
+ ".next",
61
+ "coverage",
62
+ ".harness",
63
+ ]);
64
+ const CANDIDATE = /\.(ya?ml|json)$/i;
65
+ /** Every requirement's `api=` references, from spec.md and the capability specs. */
66
+ function apiCitations(projectDir) {
67
+ const files = [path.join(projectDir, "spec.md")];
68
+ const caps = path.join(projectDir, ChangeWorkspace_1.CAPABILITIES_DIR);
69
+ if (fs.existsSync(caps)) {
70
+ for (const e of fs.readdirSync(caps, { withFileTypes: true })) {
71
+ if (e.isDirectory())
72
+ files.push(path.join(caps, e.name, "spec.md"));
73
+ }
74
+ }
75
+ const out = [];
76
+ for (const f of files) {
77
+ if (!fs.existsSync(f))
78
+ continue;
79
+ let requirement = "";
80
+ const lines = fs.readFileSync(f, "utf8").split(/\r?\n/);
81
+ for (let i = 0; i < lines.length; i++) {
82
+ const h = /^#{2,4}\s+(?:Requirement:\s*)?(REQ-\d+)\b/.exec(lines[i]);
83
+ if (h) {
84
+ requirement = h[1];
85
+ continue;
86
+ }
87
+ if (!requirement || !/<!--\s*specgate:trace\b/.test(lines[i]))
88
+ continue;
89
+ let comment = lines[i];
90
+ while (!comment.includes("-->") && i + 1 < lines.length)
91
+ comment += `\n${lines[++i]}`;
92
+ const api = (0, SpecParser_1.parseTraceComment)(comment).api;
93
+ if (!api)
94
+ continue;
95
+ for (const ref of api
96
+ .split(",")
97
+ .map((s) => s.trim())
98
+ .filter(Boolean)) {
99
+ out.push({ requirement, ref });
100
+ }
101
+ }
102
+ }
103
+ return out;
104
+ }
105
+ /** The contracts: every OpenAPI/AsyncAPI file found, plus those cited by path. */
106
+ function projectContracts(projectDir, cited = apiCitations(projectDir)) {
107
+ const found = {};
108
+ const read = (rel) => {
109
+ const abs = path.join(projectDir, rel);
110
+ let text;
111
+ try {
112
+ text = fs.readFileSync(abs, "utf8");
113
+ }
114
+ catch {
115
+ return;
116
+ }
117
+ if (!(0, ApiContract_1.contractKind)(text))
118
+ return;
119
+ found[rel.replace(/\\/g, "/")] = (0, ApiContract_1.contractOperations)(text, rel);
120
+ };
121
+ const walk = (rel, depth) => {
122
+ if (depth > 6)
123
+ return;
124
+ let entries;
125
+ try {
126
+ entries = fs.readdirSync(path.join(projectDir, rel), { withFileTypes: true });
127
+ }
128
+ catch {
129
+ return;
130
+ }
131
+ for (const e of entries) {
132
+ if (SKIP.has(e.name) || e.name.startsWith("."))
133
+ continue;
134
+ const p = rel ? `${rel}/${e.name}` : e.name;
135
+ if (e.isDirectory())
136
+ walk(p, depth + 1);
137
+ else if (CANDIDATE.test(e.name) && /openapi|asyncapi|swagger|contract|api/i.test(p))
138
+ read(p);
139
+ }
140
+ };
141
+ walk("", 0);
142
+ for (const c of cited) {
143
+ const { file } = (0, ApiContract_1.parseApiRef)(c.ref);
144
+ const norm = file.replace(/\\/g, "/").replace(/^\.\//, "");
145
+ if (norm && !found[norm] && fs.existsSync(path.join(projectDir, norm)))
146
+ read(norm);
147
+ }
148
+ return found;
149
+ }
150
+ /** `validate`'s findings: each reference that does not resolve (REQ-335). */
151
+ function apiReferenceProblems(projectDir) {
152
+ const cited = apiCitations(projectDir);
153
+ if (cited.length === 0)
154
+ return [];
155
+ const contracts = projectContracts(projectDir, cited);
156
+ const problems = [];
157
+ for (const c of cited) {
158
+ const r = (0, ApiContract_1.resolveApiRef)(c.ref, contracts);
159
+ if (r.ok)
160
+ continue;
161
+ problems.push(r.reason === "contract_missing"
162
+ ? (0, diagnostics_1.error)("api_contract_missing", `${c.requirement} cites api=${c.ref}, and ${r.file} is not a contract in this project.`, {
163
+ target: c.requirement,
164
+ fix: `Correct the path in ${c.requirement}'s specgate:trace comment, or add the contract.`,
165
+ })
166
+ : (0, diagnostics_1.error)("api_operation_missing", `${c.requirement} cites api=${c.ref}, which is not an operation of ${r.file || "any contract in this project"}.`, {
167
+ target: c.requirement,
168
+ fix: `Correct the operation in ${c.requirement}'s specgate:trace comment, or add it to the contract.`,
169
+ }));
170
+ }
171
+ return problems;
172
+ }
173
+ /** `specgate contract check` (REQ-336). */
174
+ function contractReport(projectDir) {
175
+ const cited = apiCitations(projectDir);
176
+ const contracts = projectContracts(projectDir, cited);
177
+ const status = apiReferenceProblems(projectDir);
178
+ const citedBy = new Map();
179
+ for (const c of cited) {
180
+ const r = (0, ApiContract_1.resolveApiRef)(c.ref, contracts);
181
+ if (!r.ok)
182
+ continue;
183
+ const key = `${r.file}#${r.operation.pointer}`;
184
+ citedBy.set(key, [...(citedBy.get(key) || []), c.requirement]);
185
+ }
186
+ const report = { contracts: [] };
187
+ for (const [file, ops] of Object.entries(contracts).sort(([a], [b]) => a.localeCompare(b))) {
188
+ const entry = {
189
+ file,
190
+ kind: ops[0]?.kind || "",
191
+ operations: ops.length,
192
+ cited: [],
193
+ uncited: [],
194
+ };
195
+ for (const op of ops) {
196
+ const by = citedBy.get(`${file}#${op.pointer}`);
197
+ if (by)
198
+ entry.cited.push(`${op.label} — ${[...new Set(by)].join(", ")}`);
199
+ else {
200
+ entry.uncited.push(op.label);
201
+ status.push((0, diagnostics_1.warning)("api_operation_uncited", `${file}: ${op.label} is cited by no requirement.`, {
202
+ target: op.operationId || op.pointer,
203
+ fix: `Specify it: a requirement whose specgate:trace says api=${file}#${op.operationId || op.pointer}.`,
204
+ }));
205
+ }
206
+ }
207
+ report.contracts.push(entry);
208
+ }
209
+ return { report, status };
210
+ }
211
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../../scripts/lib/contracts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /**
3
+ * Behaviour changed without a specification (REQ-333, REQ-334).
4
+ *
5
+ * A commit since the base drifts when it changes production code, its message
6
+ * names no requirement, and no test file it changes names one: a person
7
+ * patched the product and the specification never heard of it. The harness's
8
+ * commits name their requirement, so they never drift.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.isProductionFile = isProductionFile;
12
+ exports.driftSince = driftSince;
13
+ exports.driftFindings = driftFindings;
14
+ const node_child_process_1 = require("node:child_process");
15
+ const diagnostics_1 = require("./diagnostics");
16
+ const quality_run_1 = require("./quality-run");
17
+ const REQ = /\bREQ-\d+\b/;
18
+ const SOURCE = /\.(ts|tsx|js|jsx|mjs|cjs|java|kt|scala|groovy|py|go|rs|cs|fs|rb|php|swift|vue|svelte|sql|c|cc|cpp|h|hpp)$/i;
19
+ const NOT_PRODUCTION = [
20
+ /(^|\/)(tests?|__tests__|__mocks__|spec|specs|e2e|fixtures|testdata)\//i,
21
+ /(^|\/)src\/(test|it|integrationTest)\//i,
22
+ /\.(test|spec|e2e|stories)\.[^/]+$/i,
23
+ /(Test|Tests|IT|Spec)\.(java|kt|scala|groovy|cs)$/,
24
+ /(^|\/)(docs|features|\.github|\.specgate|\.harness)\//,
25
+ /(^|[/.])(eslint|prettier|vite|vitest|jest|playwright|next|webpack|rollup|tailwind|postcss|babel|tsup)\.config\.[^/]+$/i,
26
+ /(^|\/)build\.gradle(\.kts)?$|(^|\/)settings\.gradle(\.kts)?$/,
27
+ ];
28
+ function isProductionFile(file) {
29
+ const f = file.replace(/\\/g, "/");
30
+ return SOURCE.test(f) && !NOT_PRODUCTION.some((re) => re.test(f));
31
+ }
32
+ function isTestFile(file) {
33
+ const f = file.replace(/\\/g, "/");
34
+ return NOT_PRODUCTION.slice(0, 4).some((re) => re.test(f));
35
+ }
36
+ function git(dir, args) {
37
+ return (0, node_child_process_1.spawnSync)("git", ["-C", dir, ...args], { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 });
38
+ }
39
+ function driftSince(projectDir, explicitBase = "") {
40
+ const base = (0, quality_run_1.baseOf)(projectDir, explicitBase);
41
+ if (!base)
42
+ return { base: "", commits: [] };
43
+ const list = git(projectDir, ["rev-list", "--no-merges", "--reverse", `${base}..HEAD`]);
44
+ if (list.status !== 0)
45
+ return { base, commits: [] };
46
+ const commits = [];
47
+ for (const sha of (list.stdout || "").split("\n").filter(Boolean)) {
48
+ const message = git(projectDir, ["log", "-1", "--format=%B", sha]).stdout || "";
49
+ if (REQ.test(message))
50
+ continue;
51
+ const files = (git(projectDir, ["diff-tree", "--no-commit-id", "--name-only", "-r", "--root", sha]).stdout ||
52
+ "")
53
+ .split("\n")
54
+ .filter(Boolean);
55
+ const production = files.filter(isProductionFile);
56
+ if (production.length === 0)
57
+ continue;
58
+ const namedByATest = files.filter(isTestFile).some((f) => {
59
+ const shown = git(projectDir, ["show", `${sha}:${f}`]);
60
+ return shown.status === 0 && REQ.test(shown.stdout || "");
61
+ });
62
+ if (namedByATest)
63
+ continue;
64
+ commits.push({
65
+ sha: sha.slice(0, 12),
66
+ subject: message.split("\n")[0].trim(),
67
+ files: production,
68
+ });
69
+ }
70
+ return { base, commits };
71
+ }
72
+ /** One finding per drifting commit; errors when the project gates on drift. */
73
+ function driftFindings(report, gate) {
74
+ const make = gate ? diagnostics_1.error : diagnostics_1.warning;
75
+ return report.commits.map((c) => make("spec_drift", `${c.sha} "${c.subject}" changes ${c.files.join(", ")} and names no requirement, nor does any test it changes.`, {
76
+ target: c.sha,
77
+ fix: 'Name the requirement it serves in the commit and a test, or specify the behaviour first: specgate new "<behaviour>".',
78
+ }));
79
+ }
80
+ //# sourceMappingURL=drift.js.map