@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.
- package/README.md +50 -2
- package/dist/cli/index.js +110 -7
- package/dist/core/agenthook.js +41 -0
- package/dist/core/correctionStage.js +513 -0
- package/dist/core/declarationClusters.js +321 -0
- package/dist/core/delivery.js +307 -6
- package/dist/core/evidenceMap.js +202 -0
- package/dist/core/jsonc.js +72 -0
- package/dist/core/pipeline.js +953 -10
- package/dist/extractors/adrImport.js +15 -2
- package/dist/extractors/correctionSources.js +40 -0
- package/dist/extractors/landscapeDiscovery.js +1205 -0
- package/dist/integrations/providers.js +2 -78
- package/dist/integrations/scaffold.js +6 -0
- package/dist/mcp/server.js +84 -2
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
* accepted -> status accepted (live)
|
|
8
8
|
* proposed/draft -> status proposed
|
|
9
9
|
* rejected -> status rejected
|
|
10
|
-
* superseded
|
|
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
|
-
|
|
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
|