@davesheffer/hunch 1.18.0 → 1.19.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.
@@ -7,7 +7,10 @@
7
7
  * accepted -> status accepted (live)
8
8
  * proposed/draft -> status proposed
9
9
  * rejected -> status rejected
10
- * superseded/deprecated -> status superseded, valid_to closed (bi-temporal)
10
+ * superseded -> status superseded, valid_to closed (bi-temporal)
11
+ * deprecated + successor -> status superseded, closed at the successor date
12
+ * deprecated, bare -> status accepted with a loud review warning; the raw
13
+ * lifecycle remains in provenance evidence
11
14
  * "Considered Options" minus the chosen one -> alternatives_rejected
12
15
  * file slug -> topic `adr.<slug>` (namespaced so an import can never
13
16
  * collide with a live hand-captured topic; the CLI still
@@ -102,7 +105,14 @@ function refNumbers(text) {
102
105
  }
103
106
  function mapStatus(raw) {
104
107
  const s = raw.toLowerCase();
105
- if (/supersed|deprecat/.test(s))
108
+ // MADR permits a bare `deprecated` lifecycle with no replacement relation.
109
+ // Hunch has no deprecated Decision status, and inventing `superseded` would
110
+ // silently fabricate a history edge and remove the record from live recall.
111
+ // Keep it advisory/live unless an explicit successor below proves closure;
112
+ // provenance retains the source status and the mapper emits a warning.
113
+ if (/deprecat/.test(s))
114
+ return "accepted";
115
+ if (/supersed/.test(s))
106
116
  return "superseded";
107
117
  if (/reject/.test(s))
108
118
  return "rejected";
@@ -225,6 +235,9 @@ export function mapAdrCorpus(sources) {
225
235
  }
226
236
  const decisions = parsed.map((p) => {
227
237
  const successor = p.supersededByNumbers.map((n) => byNumber.get(n)).find(Boolean) ?? null;
238
+ if (/deprecat/i.test(p.statusRaw) && !successor) {
239
+ warnings.push(`${p.relPath}: deprecated status names no resolvable successor — kept in force as accepted; raw status remains in provenance evidence, review and record an explicit successor or rejection`);
240
+ }
228
241
  const superseded = p.status === "superseded" || !!successor;
229
242
  const validTo = superseded ? (successor?.date ?? p.date) : null;
230
243
  const alternatives = p.consideredOptions.filter((o) => !p.chosenOption || o.toLowerCase() !== p.chosenOption.toLowerCase());
@@ -0,0 +1,40 @@
1
+ import { correctionStagePathPattern, inferIssueCorrectionStage, } from "../core/correctionStage.js";
2
+ import { compareCodeUnits } from "../core/canonicalOrder.js";
3
+ import { repoSourceInventory } from "./repoSource.js";
4
+ const SOURCE_FILE_LIMIT = 4_000;
5
+ const SOURCE_BYTE_LIMIT = 64 * 1024 * 1024;
6
+ /** Safely read a bounded working-tree TypeScript corpus. Stage-relevant paths
7
+ * are read first so a huge repository cannot crowd the likely correction layer
8
+ * out of the fixed source budget. */
9
+ export function collectCorrectionStageSources(root, issue) {
10
+ const pattern = correctionStagePathPattern(inferIssueCorrectionStage(issue), issue);
11
+ const eligible = repoSourceInventory(root, { kind: "working" }).entries
12
+ .filter((entry) => /^[A-Za-z0-9._/-]+\.tsx?$/.test(entry.path)
13
+ && !/(?:^|\/)(?:tests?|__tests__)(?:\/|$)|\.test\.tsx?$/.test(entry.path))
14
+ .sort((a, b) => Number(pattern.test(b.path)) - Number(pattern.test(a.path)) || compareCodeUnits(a.path, b.path));
15
+ const attempted = eligible.slice(0, SOURCE_FILE_LIMIT);
16
+ const sources = [];
17
+ let bytesRead = 0;
18
+ let filesSkipped = eligible.length - attempted.length;
19
+ for (const entry of attempted) {
20
+ const read = entry.read();
21
+ if (read.source === null) {
22
+ filesSkipped++;
23
+ continue;
24
+ }
25
+ const bytes = Buffer.byteLength(read.source, "utf8");
26
+ if (bytesRead + bytes > SOURCE_BYTE_LIMIT) {
27
+ filesSkipped++;
28
+ continue;
29
+ }
30
+ sources.push({ path: entry.path, content: read.source });
31
+ bytesRead += bytes;
32
+ }
33
+ return {
34
+ sources,
35
+ files_read: sources.length,
36
+ bytes_read: bytesRead,
37
+ files_skipped: filesSkipped,
38
+ };
39
+ }
40
+ //# sourceMappingURL=correctionSources.js.map