soturail 0.3.1 → 0.3.3
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 +22 -5
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +23 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/bench.d.ts +4 -1
- package/dist/commands/bench.js +169 -14
- package/dist/commands/bench.js.map +1 -1
- package/dist/commands/dedupe.js +15 -6
- package/dist/commands/dedupe.js.map +1 -1
- package/dist/commands/expand.d.ts +5 -0
- package/dist/commands/expand.js +22 -2
- package/dist/commands/expand.js.map +1 -1
- package/dist/commands/release.js +14 -1
- package/dist/commands/release.js.map +1 -1
- package/dist/commands/run.d.ts +2 -0
- package/dist/commands/run.js +49 -3
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/stats.d.ts +6 -0
- package/dist/commands/stats.js +25 -1
- package/dist/commands/stats.js.map +1 -1
- package/dist/compressors/developer-reducer.d.ts +3 -0
- package/dist/compressors/developer-reducer.js +90 -0
- package/dist/compressors/developer-reducer.js.map +1 -0
- package/dist/compressors/index.js +11 -0
- package/dist/compressors/index.js.map +1 -1
- package/dist/core/block-dedupe.d.ts +43 -0
- package/dist/core/block-dedupe.js +82 -0
- package/dist/core/block-dedupe.js.map +1 -0
- package/dist/core/config.d.ts +38 -0
- package/dist/core/config.js +18 -1
- package/dist/core/config.js.map +1 -1
- package/dist/core/dedupe-store.d.ts +38 -0
- package/dist/core/dedupe-store.js +45 -2
- package/dist/core/dedupe-store.js.map +1 -1
- package/dist/core/release-preflight.d.ts +9 -0
- package/dist/core/release-preflight.js +174 -3
- package/dist/core/release-preflight.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/docs/benchmarking.md +12 -2
- package/docs/comparisons.md +1 -1
- package/docs/metrics.md +9 -0
- package/docs/reducers.md +31 -0
- package/docs/release-checklist.md +10 -0
- package/docs/release-workflow.md +12 -0
- package/docs/security-model.md +13 -1
- package/docs/windows.md +3 -1
- package/package.json +1 -1
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { estimateTokens } from "./token-estimator.js";
|
|
2
|
+
import { sha256Text } from "./dedupe-store.js";
|
|
3
|
+
const RISK_PATTERN = /\b(error|failed|failure|exception|warning|warn|security|vulnerability|traceback|assertion|denied|permission|refused|timeout)\b|(?:^|\s)at\s+[\w.$<>]+\(.*:\d+\)|[\w./\\-]+\.(?:ts|tsx|js|jsx|py|java|go|rs|md):\d+(?::\d+)?/i;
|
|
4
|
+
export function normalizeBlockForDedupe(text) {
|
|
5
|
+
return text
|
|
6
|
+
.replace(/\b\d{4}-\d{2}-\d{2}[T\s]\d{2}:\d{2}:\d{2}(?:\.\d+)?Z?\b/g, "<timestamp>")
|
|
7
|
+
.replace(/\b\d{2}:\d{2}:\d{2}(?:\.\d+)?\b/g, "<time>")
|
|
8
|
+
.replace(/[A-Z]:\\(?:Users|Temp|tmp)\\[^\s]+/gi, "<path>")
|
|
9
|
+
.replace(/\/(?:tmp|var\/folders|private\/tmp)\/[^\s]+/g, "<path>")
|
|
10
|
+
.replace(/\s+/g, " ")
|
|
11
|
+
.trim()
|
|
12
|
+
.toLowerCase();
|
|
13
|
+
}
|
|
14
|
+
export function blockHasRisk(text) {
|
|
15
|
+
return RISK_PATTERN.test(text);
|
|
16
|
+
}
|
|
17
|
+
export async function applyBlockDedupe(rawText, lookup, options) {
|
|
18
|
+
const lines = rawText.split(/\r?\n/);
|
|
19
|
+
const blockMinLines = Math.max(1, options.blockMinLines);
|
|
20
|
+
const output = [];
|
|
21
|
+
const newBlocks = [];
|
|
22
|
+
const reusedBlocks = [];
|
|
23
|
+
const seenCurrent = new Set();
|
|
24
|
+
const createdAt = new Date().toISOString();
|
|
25
|
+
for (let index = 0; index < lines.length; index += blockMinLines) {
|
|
26
|
+
const blockLines = lines.slice(index, index + blockMinLines);
|
|
27
|
+
const blockText = blockLines.join("\n");
|
|
28
|
+
const nonEmpty = blockText.trim().length > 0;
|
|
29
|
+
if (!nonEmpty || blockLines.length < blockMinLines) {
|
|
30
|
+
output.push(blockText);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const hash = sha256Text(blockText);
|
|
34
|
+
const normalized = normalizeBlockForDedupe(blockText);
|
|
35
|
+
const normalizedHash = sha256Text(normalized);
|
|
36
|
+
const risky = blockHasRisk(blockText);
|
|
37
|
+
const firstInCurrent = !seenCurrent.has(hash);
|
|
38
|
+
seenCurrent.add(hash);
|
|
39
|
+
const blockId = `block_${hash.slice(0, 8)}`;
|
|
40
|
+
const tokenEstimate = estimateTokens(blockText);
|
|
41
|
+
newBlocks.push({
|
|
42
|
+
block_id: blockId,
|
|
43
|
+
block_sha256: hash,
|
|
44
|
+
normalized_sha256: normalizedHash,
|
|
45
|
+
raw_id: options.rawId,
|
|
46
|
+
line_count: blockLines.length,
|
|
47
|
+
token_estimate: tokenEstimate,
|
|
48
|
+
has_risk: risky,
|
|
49
|
+
preview: blockLines.slice(0, 2).join(" | ").slice(0, 240),
|
|
50
|
+
created_at: createdAt
|
|
51
|
+
});
|
|
52
|
+
if (!firstInCurrent || (options.preserveErrorBlocks && risky)) {
|
|
53
|
+
output.push(blockText);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const previous = await lookup.findReusableBlock(hash, normalizedHash, {
|
|
57
|
+
recentWindow: options.recentWindow,
|
|
58
|
+
allowSimilar: options.similarMode === "conservative" && !risky
|
|
59
|
+
});
|
|
60
|
+
if (!previous) {
|
|
61
|
+
output.push(blockText);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const tokensSaved = Math.max(0, tokenEstimate - estimateTokens(previous.block_id));
|
|
65
|
+
reusedBlocks.push({
|
|
66
|
+
block_id: previous.block_id,
|
|
67
|
+
current_raw_id: options.rawId,
|
|
68
|
+
previous_raw_id: previous.raw_id,
|
|
69
|
+
line_count: blockLines.length,
|
|
70
|
+
tokens_saved: tokensSaved,
|
|
71
|
+
created_at: createdAt
|
|
72
|
+
});
|
|
73
|
+
output.push(`[deduped block: ${previous.block_id}, seen in raw_id ${previous.raw_id}, ${blockLines.length} lines]`);
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
output: output.join("\n"),
|
|
77
|
+
reusedBlocks,
|
|
78
|
+
newBlocks,
|
|
79
|
+
tokensSaved: reusedBlocks.reduce((sum, hit) => sum + hit.tokens_saved, 0)
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=block-dedupe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-dedupe.js","sourceRoot":"","sources":["../../src/core/block-dedupe.ts"],"names":[],"mappings":"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"}
|
package/dist/core/config.d.ts
CHANGED
|
@@ -27,6 +27,28 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
27
27
|
}, {
|
|
28
28
|
dynamic_footer_token_budget?: number | undefined;
|
|
29
29
|
}>>;
|
|
30
|
+
dedupe: z.ZodDefault<z.ZodObject<{
|
|
31
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
32
|
+
mode: z.ZodDefault<z.ZodEnum<["conservative"]>>;
|
|
33
|
+
blockMinLines: z.ZodDefault<z.ZodNumber>;
|
|
34
|
+
recentWindow: z.ZodDefault<z.ZodNumber>;
|
|
35
|
+
preserveErrorBlocks: z.ZodDefault<z.ZodBoolean>;
|
|
36
|
+
similar_dedupe: z.ZodDefault<z.ZodEnum<["off", "conservative"]>>;
|
|
37
|
+
}, "strip", z.ZodTypeAny, {
|
|
38
|
+
enabled: boolean;
|
|
39
|
+
mode: "conservative";
|
|
40
|
+
blockMinLines: number;
|
|
41
|
+
recentWindow: number;
|
|
42
|
+
preserveErrorBlocks: boolean;
|
|
43
|
+
similar_dedupe: "conservative" | "off";
|
|
44
|
+
}, {
|
|
45
|
+
enabled?: boolean | undefined;
|
|
46
|
+
mode?: "conservative" | undefined;
|
|
47
|
+
blockMinLines?: number | undefined;
|
|
48
|
+
recentWindow?: number | undefined;
|
|
49
|
+
preserveErrorBlocks?: boolean | undefined;
|
|
50
|
+
similar_dedupe?: "conservative" | "off" | undefined;
|
|
51
|
+
}>>;
|
|
30
52
|
}, "strip", z.ZodTypeAny, {
|
|
31
53
|
schema_version: 1;
|
|
32
54
|
project_name: string;
|
|
@@ -41,6 +63,14 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
41
63
|
cache: {
|
|
42
64
|
dynamic_footer_token_budget: number;
|
|
43
65
|
};
|
|
66
|
+
dedupe: {
|
|
67
|
+
enabled: boolean;
|
|
68
|
+
mode: "conservative";
|
|
69
|
+
blockMinLines: number;
|
|
70
|
+
recentWindow: number;
|
|
71
|
+
preserveErrorBlocks: boolean;
|
|
72
|
+
similar_dedupe: "conservative" | "off";
|
|
73
|
+
};
|
|
44
74
|
}, {
|
|
45
75
|
schema_version?: 1 | undefined;
|
|
46
76
|
project_name?: string | undefined;
|
|
@@ -55,6 +85,14 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
55
85
|
cache?: {
|
|
56
86
|
dynamic_footer_token_budget?: number | undefined;
|
|
57
87
|
} | undefined;
|
|
88
|
+
dedupe?: {
|
|
89
|
+
enabled?: boolean | undefined;
|
|
90
|
+
mode?: "conservative" | undefined;
|
|
91
|
+
blockMinLines?: number | undefined;
|
|
92
|
+
recentWindow?: number | undefined;
|
|
93
|
+
preserveErrorBlocks?: boolean | undefined;
|
|
94
|
+
similar_dedupe?: "conservative" | "off" | undefined;
|
|
95
|
+
} | undefined;
|
|
58
96
|
}>;
|
|
59
97
|
export type SotuRailConfig = z.infer<typeof ConfigSchema>;
|
|
60
98
|
export declare const defaultConfig: SotuRailConfig;
|
package/dist/core/config.js
CHANGED
|
@@ -37,7 +37,24 @@ export const ConfigSchema = z.object({
|
|
|
37
37
|
.object({
|
|
38
38
|
dynamic_footer_token_budget: z.number().int().positive().max(10000).default(800)
|
|
39
39
|
})
|
|
40
|
-
.default({ dynamic_footer_token_budget: 800 })
|
|
40
|
+
.default({ dynamic_footer_token_budget: 800 }),
|
|
41
|
+
dedupe: z
|
|
42
|
+
.object({
|
|
43
|
+
enabled: z.boolean().default(true),
|
|
44
|
+
mode: z.enum(["conservative"]).default("conservative"),
|
|
45
|
+
blockMinLines: z.number().int().positive().max(1000).default(8),
|
|
46
|
+
recentWindow: z.number().int().positive().max(1000).default(10),
|
|
47
|
+
preserveErrorBlocks: z.boolean().default(true),
|
|
48
|
+
similar_dedupe: z.enum(["off", "conservative"]).default("off")
|
|
49
|
+
})
|
|
50
|
+
.default({
|
|
51
|
+
enabled: true,
|
|
52
|
+
mode: "conservative",
|
|
53
|
+
blockMinLines: 8,
|
|
54
|
+
recentWindow: 10,
|
|
55
|
+
preserveErrorBlocks: true,
|
|
56
|
+
similar_dedupe: "off"
|
|
57
|
+
})
|
|
41
58
|
});
|
|
42
59
|
export const defaultConfig = ConfigSchema.parse({});
|
|
43
60
|
export function getWorkspacePaths(root = process.cwd(), workspaceDir = WORKSPACE_DIR) {
|
package/dist/core/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC;AAEzC,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,KAAK;IACL,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,IAAI;IACJ,OAAO;IACP,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;CACG,CAAC;AAEX,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACvC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,kBAAkB,CAAC;IACpD,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC;IAChD,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;IACrE,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,yBAAyB,CAAC,CAAC;IAC9E,oBAAoB,EAAE,CAAC;SACpB,MAAM,CAAC;QACN,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC3G,oBAAoB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QAC/C,0BAA0B,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;KACtD,CAAC;SACD,OAAO,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE,0BAA0B,EAAE,IAAI,EAAE,CAAC;IACpG,KAAK,EAAE,CAAC;SACL,MAAM,CAAC;QACN,2BAA2B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;KACjF,CAAC;SACD,OAAO,CAAC,EAAE,2BAA2B,EAAE,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC;AAEzC,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,KAAK;IACL,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,IAAI;IACJ,OAAO;IACP,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;CACG,CAAC;AAEX,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACvC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,kBAAkB,CAAC;IACpD,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC;IAChD,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;IACrE,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,yBAAyB,CAAC,CAAC;IAC9E,oBAAoB,EAAE,CAAC;SACpB,MAAM,CAAC;QACN,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC3G,oBAAoB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QAC/C,0BAA0B,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;KACtD,CAAC;SACD,OAAO,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE,0BAA0B,EAAE,IAAI,EAAE,CAAC;IACpG,KAAK,EAAE,CAAC;SACL,MAAM,CAAC;QACN,2BAA2B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;KACjF,CAAC;SACD,OAAO,CAAC,EAAE,2BAA2B,EAAE,GAAG,EAAE,CAAC;IAChD,MAAM,EAAE,CAAC;SACN,MAAM,CAAC;QACN,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QAClC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC;QACtD,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QAC/D,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/D,mBAAmB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QAC9C,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;KAC/D,CAAC;SACD,OAAO,CAAC;QACP,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,cAAc;QACpB,aAAa,EAAE,CAAC;QAChB,YAAY,EAAE,EAAE;QAChB,mBAAmB,EAAE,IAAI;QACzB,cAAc,EAAE,KAAK;KACtB,CAAC;CACL,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,aAAa,GAAmB,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAwCpE,MAAM,UAAU,iBAAiB,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,GAAG,aAAa;IAClF,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IAC3D,OAAO;QACL,IAAI,EAAE,YAAY;QAClB,SAAS;QACT,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC;QAC5C,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,aAAa,CAAC;QAC5D,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC;QACtC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,aAAa,CAAC;QACvD,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC;QAC9C,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC;QAC5C,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,cAAc,CAAC;QAC7D,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC;QAC1C,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC;QAC9C,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,cAAc,CAAC;QAC/D,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC;QAC1C,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,CAAC;QAC7D,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC;QAC5C,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,aAAa,CAAC;QAC7D,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC;QAC1C,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC;QAC1D,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC;QAC1C,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,EAAE,WAAW,CAAC;QACxD,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,CAAC;QAChE,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,EAAE,gBAAgB,CAAC;QAClE,kBAAkB,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC;QAClE,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,eAAe,CAAC;QACrE,kBAAkB,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,gBAAgB,CAAC;QACvE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC;QAC5C,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC;QAC9C,eAAe,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC;QAC7D,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC;QAC3D,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC;KAC/C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,YAAoB;IAC/D,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACvF,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,QAAgB;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe,EAAE,MAAqB,EAAE,IAAa;IACnF,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9C,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAgB,EAChB,OAAe,EACf,MAAqB,EACrB,IAAa;IAEb,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACjE,IAAI,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9C,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;IACxD,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,MAAM,GAAiB,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC1D,MAAM,IAAI,GAAG;QACX,KAAK,CAAC,SAAS;QACf,KAAK,CAAC,SAAS;QACf,KAAK,CAAC,MAAM;QACZ,KAAK,CAAC,UAAU;QAChB,KAAK,CAAC,SAAS;QACf,KAAK,CAAC,QAAQ;QACd,KAAK,CAAC,UAAU;QAChB,KAAK,CAAC,QAAQ;QACd,KAAK,CAAC,SAAS;QACf,KAAK,CAAC,QAAQ;QACd,KAAK,CAAC,QAAQ;QACd,KAAK,CAAC,kBAAkB;QACxB,KAAK,CAAC,SAAS;QACf,KAAK,CAAC,UAAU;QAChB,KAAK,CAAC,eAAe;QACrB,KAAK,CAAC,cAAc;QACpB,KAAK,CAAC,UAAU;KACjB,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,kBAAkB,CAAC,KAAK,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9G,MAAM,kBAAkB,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACjE,MAAM,kBAAkB,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACnE,MAAM,kBAAkB,CAAC,KAAK,CAAC,iBAAiB,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1E,MAAM,kBAAkB,CAAC,KAAK,CAAC,kBAAkB,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3E,MAAM,kBAAkB,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACpE,MAAM,kBAAkB,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACpE,MAAM,kBAAkB,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACpE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;IACnD,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACxD,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,OAAO,aAAa,CAAC;QACvB,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;IAC3D,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACxD,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACpC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACxF,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB,EAAE,KAAc;IAChE,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,MAAM,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAI,QAAgB;IACjD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAChD,OAAO,GAAG;aACP,KAAK,CAAC,OAAO,CAAC;aACd,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;aACxC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAgB,EAAE,KAAc;IAC9D,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC9E,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export interface DedupeRecord {
|
|
2
|
+
kind?: "output";
|
|
2
3
|
output_sha256: string;
|
|
3
4
|
raw_id: string;
|
|
4
5
|
command: string;
|
|
@@ -6,6 +7,27 @@ export interface DedupeRecord {
|
|
|
6
7
|
raw_path: string;
|
|
7
8
|
created_at: string;
|
|
8
9
|
}
|
|
10
|
+
export interface DedupeBlockRecord {
|
|
11
|
+
kind: "block";
|
|
12
|
+
block_id: string;
|
|
13
|
+
block_sha256: string;
|
|
14
|
+
normalized_sha256: string;
|
|
15
|
+
raw_id: string;
|
|
16
|
+
line_count: number;
|
|
17
|
+
token_estimate: number;
|
|
18
|
+
has_risk: boolean;
|
|
19
|
+
preview: string;
|
|
20
|
+
created_at: string;
|
|
21
|
+
}
|
|
22
|
+
export interface DedupeBlockHitRecord {
|
|
23
|
+
kind: "block_hit";
|
|
24
|
+
block_id: string;
|
|
25
|
+
current_raw_id: string;
|
|
26
|
+
previous_raw_id: string;
|
|
27
|
+
line_count: number;
|
|
28
|
+
tokens_saved: number;
|
|
29
|
+
created_at: string;
|
|
30
|
+
}
|
|
9
31
|
export declare function sha256Text(text: string): string;
|
|
10
32
|
export declare class DedupeStore {
|
|
11
33
|
private readonly root;
|
|
@@ -13,5 +35,21 @@ export declare class DedupeStore {
|
|
|
13
35
|
findReusable(outputHash: string, exitCode: number): Promise<DedupeRecord | null>;
|
|
14
36
|
append(record: DedupeRecord): Promise<void>;
|
|
15
37
|
readAll(): Promise<DedupeRecord[]>;
|
|
38
|
+
appendBlock(record: DedupeBlockRecord): Promise<void>;
|
|
39
|
+
appendBlockHit(record: DedupeBlockHitRecord): Promise<void>;
|
|
40
|
+
readBlocks(): Promise<DedupeBlockRecord[]>;
|
|
41
|
+
readBlockHits(): Promise<DedupeBlockHitRecord[]>;
|
|
42
|
+
findReusableBlock(hash: string, normalizedHash: string, options: {
|
|
43
|
+
recentWindow: number;
|
|
44
|
+
allowSimilar: boolean;
|
|
45
|
+
}): Promise<DedupeBlockRecord | null>;
|
|
46
|
+
stats(): Promise<{
|
|
47
|
+
outputRecords: number;
|
|
48
|
+
uniqueOutputHashes: number;
|
|
49
|
+
recentBlocks: number;
|
|
50
|
+
dedupedBlocks: number;
|
|
51
|
+
estimatedTokensSaved: number;
|
|
52
|
+
indexPath: string;
|
|
53
|
+
}>;
|
|
16
54
|
private rawExists;
|
|
17
55
|
}
|
|
@@ -24,11 +24,54 @@ export class DedupeStore {
|
|
|
24
24
|
}
|
|
25
25
|
async append(record) {
|
|
26
26
|
const paths = getWorkspacePaths(this.root);
|
|
27
|
-
await appendJsonl(paths.dedupeIndex, record);
|
|
27
|
+
await appendJsonl(paths.dedupeIndex, { kind: "output", ...record });
|
|
28
28
|
}
|
|
29
29
|
async readAll() {
|
|
30
30
|
const paths = getWorkspacePaths(this.root);
|
|
31
|
-
|
|
31
|
+
const records = await readJsonl(paths.dedupeIndex);
|
|
32
|
+
return records.filter((record) => record.kind === undefined || record.kind === "output");
|
|
33
|
+
}
|
|
34
|
+
async appendBlock(record) {
|
|
35
|
+
const paths = getWorkspacePaths(this.root);
|
|
36
|
+
await appendJsonl(paths.dedupeIndex, record);
|
|
37
|
+
}
|
|
38
|
+
async appendBlockHit(record) {
|
|
39
|
+
const paths = getWorkspacePaths(this.root);
|
|
40
|
+
await appendJsonl(paths.dedupeIndex, record);
|
|
41
|
+
}
|
|
42
|
+
async readBlocks() {
|
|
43
|
+
const paths = getWorkspacePaths(this.root);
|
|
44
|
+
const records = await readJsonl(paths.dedupeIndex);
|
|
45
|
+
return records.filter((record) => record.kind === "block");
|
|
46
|
+
}
|
|
47
|
+
async readBlockHits() {
|
|
48
|
+
const paths = getWorkspacePaths(this.root);
|
|
49
|
+
const records = await readJsonl(paths.dedupeIndex);
|
|
50
|
+
return records.filter((record) => record.kind === "block_hit");
|
|
51
|
+
}
|
|
52
|
+
async findReusableBlock(hash, normalizedHash, options) {
|
|
53
|
+
const blocks = await this.readBlocks();
|
|
54
|
+
const recent = blocks.slice(-Math.max(1, options.recentWindow));
|
|
55
|
+
for (const block of [...recent].reverse()) {
|
|
56
|
+
if (block.block_sha256 === hash || (options.allowSimilar && block.normalized_sha256 === normalizedHash)) {
|
|
57
|
+
return block;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
async stats() {
|
|
63
|
+
const paths = getWorkspacePaths(this.root);
|
|
64
|
+
const output = await this.readAll();
|
|
65
|
+
const blocks = await this.readBlocks();
|
|
66
|
+
const hits = await this.readBlockHits();
|
|
67
|
+
return {
|
|
68
|
+
outputRecords: output.length,
|
|
69
|
+
uniqueOutputHashes: new Set(output.map((record) => record.output_sha256)).size,
|
|
70
|
+
recentBlocks: blocks.length,
|
|
71
|
+
dedupedBlocks: hits.length,
|
|
72
|
+
estimatedTokensSaved: hits.reduce((sum, hit) => sum + hit.tokens_saved, 0),
|
|
73
|
+
indexPath: path.normalize(path.relative(paths.root, paths.dedupeIndex))
|
|
74
|
+
};
|
|
32
75
|
}
|
|
33
76
|
async rawExists(rawPath) {
|
|
34
77
|
const paths = getWorkspacePaths(this.root);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dedupe-store.js","sourceRoot":"","sources":["../../src/core/dedupe-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"dedupe-store.js","sourceRoot":"","sources":["../../src/core/dedupe-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,5 +18,14 @@ export interface ReleasePreflightOptions {
|
|
|
18
18
|
runPack?: boolean;
|
|
19
19
|
cliCommand?: string[];
|
|
20
20
|
}
|
|
21
|
+
export interface PackedPackageVerification {
|
|
22
|
+
ok: boolean;
|
|
23
|
+
tarballPath: string | null;
|
|
24
|
+
cliVersion: string | null;
|
|
25
|
+
npxVersion: string | null;
|
|
26
|
+
helpExitCode?: number | null;
|
|
27
|
+
details: string;
|
|
28
|
+
}
|
|
21
29
|
export declare function runReleasePreflight(root?: string, options?: ReleasePreflightOptions): Promise<ReleasePreflightResult>;
|
|
30
|
+
export declare function verifyPackedPackage(root: string, packageName: string, version: string): Promise<PackedPackageVerification>;
|
|
22
31
|
export declare function formatReleasePreflight(result: ReleasePreflightResult): string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { promises as fs } from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
const SEMVER_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
6
7
|
export async function runReleasePreflight(root = process.cwd(), options = {}) {
|
|
@@ -34,10 +35,15 @@ export async function runReleasePreflight(root = process.cwd(), options = {}) {
|
|
|
34
35
|
const expectedTarball = packageName && version ? `${packageName}-${version}.tgz` : null;
|
|
35
36
|
addGate(gates, "npm_pack_metadata", "npm pack metadata", Boolean(pack.code === 0 && expectedTarball && combined.includes(expectedTarball)), expectedTarball ? `expected ${expectedTarball}` : "missing package name or version");
|
|
36
37
|
addGate(gates, "npm_pack_no_raw_logs", "npm pack excludes raw logs", !combined.includes(".soturail/raw") && !combined.includes("benchmarks/results/latest.json"), "pack output must not include .soturail/raw or generated benchmark JSON");
|
|
38
|
+
const packageVerification = packageName && version
|
|
39
|
+
? await verifyPackedPackage(resolvedRoot, packageName, version)
|
|
40
|
+
: { ok: false, tarballPath: null, cliVersion: null, npxVersion: null, details: "missing package name or version" };
|
|
41
|
+
addGate(gates, "packed_package_cli_version", "packed package CLI version", packageVerification.ok, packageVerification.details);
|
|
37
42
|
}
|
|
38
43
|
else {
|
|
39
44
|
addGate(gates, "npm_pack_metadata", "npm pack metadata", true, "skipped by test options", false);
|
|
40
45
|
addGate(gates, "npm_pack_no_raw_logs", "npm pack excludes raw logs", true, "skipped by test options", false);
|
|
46
|
+
addGate(gates, "packed_package_cli_version", "packed package CLI version", true, "skipped by test options", false);
|
|
41
47
|
}
|
|
42
48
|
const readme = await readOptionalText(path.join(resolvedRoot, "README.md"));
|
|
43
49
|
addGate(gates, "readme_install", "README install instructions", Boolean(readme && /npx\s+soturail/.test(readme) && readme.includes("npm install -g soturail") && readme.includes("soturail --version")), readme ? "README.md contains npm/npx/global install guidance" : "README.md missing");
|
|
@@ -71,6 +77,164 @@ export async function runReleasePreflight(root = process.cwd(), options = {}) {
|
|
|
71
77
|
gates
|
|
72
78
|
};
|
|
73
79
|
}
|
|
80
|
+
export async function verifyPackedPackage(root, packageName, version) {
|
|
81
|
+
const resolvedRoot = path.resolve(root);
|
|
82
|
+
let packRoot = null;
|
|
83
|
+
let tarballPath = null;
|
|
84
|
+
let installRoot = null;
|
|
85
|
+
try {
|
|
86
|
+
packRoot = await fs.mkdtemp(path.join(os.tmpdir(), "soturail-pack-tarball-"));
|
|
87
|
+
const pack = await runProcess("npm", ["pack", "--json", "--pack-destination", packRoot], resolvedRoot, true);
|
|
88
|
+
if (pack.code !== 0) {
|
|
89
|
+
return failPackageVerification(null, diagnosticDetails({
|
|
90
|
+
phase: "pack",
|
|
91
|
+
expectedVersion: version,
|
|
92
|
+
result: pack,
|
|
93
|
+
tarballPath: null,
|
|
94
|
+
strategy: "npm_pack_to_temp_directory"
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
const parsed = JSON.parse(pack.stdout);
|
|
98
|
+
const first = parsed[0];
|
|
99
|
+
const tgzFiles = (await fs.readdir(packRoot)).filter((file) => file.endsWith(".tgz"));
|
|
100
|
+
const filename = first?.filename ? path.basename(first.filename) : tgzFiles[0];
|
|
101
|
+
if (!filename) {
|
|
102
|
+
return failPackageVerification(null, `npm pack did not produce a .tgz in ${packRoot}\n${formatProcessResult(pack)}`);
|
|
103
|
+
}
|
|
104
|
+
tarballPath = path.resolve(packRoot, filename);
|
|
105
|
+
const files = new Set((first?.files ?? [])
|
|
106
|
+
.map((file) => file.path)
|
|
107
|
+
.filter((value) => typeof value === "string")
|
|
108
|
+
.map(normalizePackedPath));
|
|
109
|
+
const requiredFiles = ["package.json", "dist/cli.js", "dist/core/version.js", "README.md", "LICENSE"];
|
|
110
|
+
const forbidden = [...files].filter((file) => file.startsWith(".soturail/raw")
|
|
111
|
+
|| file === "benchmarks/results/latest.json"
|
|
112
|
+
|| /^soturail-\d+\.\d+\.\d+.*\.tgz$/.test(file)
|
|
113
|
+
|| /temp-pack-test|soturail-clean-smoke|soturail-test-/.test(file));
|
|
114
|
+
if (forbidden.length > 0) {
|
|
115
|
+
return failPackageVerification(tarballPath, [
|
|
116
|
+
"tarball file check failed",
|
|
117
|
+
`expected_version=${version}`,
|
|
118
|
+
`tarball_path=${tarballPath}`,
|
|
119
|
+
"missing=checked_after_install",
|
|
120
|
+
`forbidden=${forbidden.join(", ")}`,
|
|
121
|
+
`strategy=npm_pack_to_temp_directory`
|
|
122
|
+
].join("\n"));
|
|
123
|
+
}
|
|
124
|
+
installRoot = await fs.mkdtemp(path.join(os.tmpdir(), "soturail-pack-verify-"));
|
|
125
|
+
await fs.writeFile(path.join(installRoot, "package.json"), JSON.stringify({ name: "soturail-pack-verify", private: true }, null, 2), "utf8");
|
|
126
|
+
const install = await runProcess("npm", ["install", tarballPath, "--ignore-scripts"], installRoot, true);
|
|
127
|
+
if (install.code !== 0) {
|
|
128
|
+
return failPackageVerification(tarballPath, diagnosticDetails({
|
|
129
|
+
phase: "install",
|
|
130
|
+
expectedVersion: version,
|
|
131
|
+
result: install,
|
|
132
|
+
tarballPath,
|
|
133
|
+
strategy: "install_absolute_tgz_ignore_scripts"
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
const installedPackageRoot = path.join(installRoot, "node_modules", packageName);
|
|
137
|
+
const installedFiles = new Set(await listRelativeFiles(installedPackageRoot));
|
|
138
|
+
const missingInstalled = requiredFiles.filter((file) => !installedFiles.has(file));
|
|
139
|
+
const forbiddenInstalled = [...installedFiles].filter((file) => file.startsWith(".soturail/raw")
|
|
140
|
+
|| file === "benchmarks/results/latest.json"
|
|
141
|
+
|| /^soturail-\d+\.\d+\.\d+.*\.tgz$/.test(file)
|
|
142
|
+
|| /temp-pack-test|soturail-clean-smoke|soturail-test-/.test(file));
|
|
143
|
+
if (missingInstalled.length > 0 || forbiddenInstalled.length > 0) {
|
|
144
|
+
return failPackageVerification(tarballPath, [
|
|
145
|
+
"installed tarball file check failed",
|
|
146
|
+
`expected_version=${version}`,
|
|
147
|
+
`tarball_path=${tarballPath}`,
|
|
148
|
+
`installed_package_root=${installedPackageRoot}`,
|
|
149
|
+
`missing=${missingInstalled.join(", ") || "none"}`,
|
|
150
|
+
`forbidden=${forbiddenInstalled.join(", ") || "none"}`,
|
|
151
|
+
"strategy=installed_tarball_file_check"
|
|
152
|
+
].join("\n"));
|
|
153
|
+
}
|
|
154
|
+
const cliPath = path.join(installedPackageRoot, "dist", "cli.js");
|
|
155
|
+
const cli = await runProcess(process.execPath, [cliPath, "--version"], installRoot, true);
|
|
156
|
+
const help = await runProcess(process.execPath, [cliPath, "--help"], installRoot, true);
|
|
157
|
+
const cliVersion = cli.stdout.trim();
|
|
158
|
+
const ok = cli.code === 0 && help.code === 0 && cliVersion === version;
|
|
159
|
+
return {
|
|
160
|
+
ok,
|
|
161
|
+
tarballPath,
|
|
162
|
+
cliVersion,
|
|
163
|
+
npxVersion: null,
|
|
164
|
+
helpExitCode: help.code,
|
|
165
|
+
details: ok
|
|
166
|
+
? `packed cli=${cliVersion}, help_exit_code=${help.code}, tarball=${path.basename(tarballPath)}, strategy=installed_tarball_cli_no_npx_no_global`
|
|
167
|
+
: diagnosticDetails({
|
|
168
|
+
phase: "installed_cli_version",
|
|
169
|
+
expectedVersion: version,
|
|
170
|
+
actualVersion: cliVersion || null,
|
|
171
|
+
result: cli,
|
|
172
|
+
help,
|
|
173
|
+
tarballPath,
|
|
174
|
+
strategy: "installed_tarball_cli_no_npx_no_global"
|
|
175
|
+
})
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
return failPackageVerification(tarballPath, error instanceof Error ? error.message : String(error));
|
|
180
|
+
}
|
|
181
|
+
finally {
|
|
182
|
+
if (installRoot)
|
|
183
|
+
await fs.rm(installRoot, { recursive: true, force: true }).catch(() => undefined);
|
|
184
|
+
if (packRoot)
|
|
185
|
+
await fs.rm(packRoot, { recursive: true, force: true }).catch(() => undefined);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function failPackageVerification(tarballPath, details) {
|
|
189
|
+
return { ok: false, tarballPath, cliVersion: null, npxVersion: null, helpExitCode: null, details };
|
|
190
|
+
}
|
|
191
|
+
function normalizePackedPath(value) {
|
|
192
|
+
return value.replace(/^package\//, "").replace(/\\/g, "/");
|
|
193
|
+
}
|
|
194
|
+
async function listRelativeFiles(root) {
|
|
195
|
+
const output = [];
|
|
196
|
+
async function visit(dir) {
|
|
197
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
198
|
+
for (const entry of entries) {
|
|
199
|
+
const absolute = path.join(dir, entry.name);
|
|
200
|
+
if (entry.isDirectory()) {
|
|
201
|
+
await visit(absolute);
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
if (entry.isFile()) {
|
|
205
|
+
output.push(path.relative(root, absolute).replace(/\\/g, "/"));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
await visit(root);
|
|
210
|
+
return output;
|
|
211
|
+
}
|
|
212
|
+
function diagnosticDetails(input) {
|
|
213
|
+
return [
|
|
214
|
+
`phase=${input.phase}`,
|
|
215
|
+
`strategy=${input.strategy}`,
|
|
216
|
+
"cache_usage=none",
|
|
217
|
+
"global_cli_usage=none",
|
|
218
|
+
"npx_usage=none",
|
|
219
|
+
"npm_exec_usage=none",
|
|
220
|
+
"local_repo_dist_usage=none",
|
|
221
|
+
`expected ${input.expectedVersion}`,
|
|
222
|
+
`expected_version=${input.expectedVersion}`,
|
|
223
|
+
`actual_version=${(input.actualVersion ?? input.result.stdout.trim()) || "empty"}`,
|
|
224
|
+
`tarball_path=${input.tarballPath ?? "none"}`,
|
|
225
|
+
formatProcessResult(input.result),
|
|
226
|
+
...(input.help ? [`help_check:\n${formatProcessResult(input.help)}`] : [])
|
|
227
|
+
].join("\n");
|
|
228
|
+
}
|
|
229
|
+
function formatProcessResult(result) {
|
|
230
|
+
return [
|
|
231
|
+
`command=${[result.command, ...result.args].join(" ")}`,
|
|
232
|
+
`cwd=${result.cwd}`,
|
|
233
|
+
`exit_code=${result.code}`,
|
|
234
|
+
`stdout=${result.stdout.trim() || "<empty>"}`,
|
|
235
|
+
`stderr=${result.stderr.trim() || "<empty>"}`
|
|
236
|
+
].join("\n");
|
|
237
|
+
}
|
|
74
238
|
export function formatReleasePreflight(result) {
|
|
75
239
|
const lines = [
|
|
76
240
|
`Release preflight: ${result.ok ? "passed" : "failed"}`,
|
|
@@ -89,12 +253,19 @@ async function readCliVersion(root, cliCommand) {
|
|
|
89
253
|
const command = cliCommand[0];
|
|
90
254
|
const args = cliCommand.slice(1);
|
|
91
255
|
if (!command)
|
|
92
|
-
return { code: 1, stdout: "", stderr: "empty CLI command" };
|
|
256
|
+
return { code: 1, stdout: "", stderr: "empty CLI command", command: "", args: [], cwd: root };
|
|
93
257
|
return runProcess(command, args, root, true);
|
|
94
258
|
}
|
|
95
259
|
const cliPath = path.join(root, "dist", "cli.js");
|
|
96
260
|
if (!existsSync(cliPath)) {
|
|
97
|
-
return {
|
|
261
|
+
return {
|
|
262
|
+
code: 1,
|
|
263
|
+
stdout: "",
|
|
264
|
+
stderr: "dist/cli.js is missing; run npm run build first",
|
|
265
|
+
command: process.execPath,
|
|
266
|
+
args: [cliPath, "--version"],
|
|
267
|
+
cwd: root
|
|
268
|
+
};
|
|
98
269
|
}
|
|
99
270
|
return runProcess(process.execPath, [cliPath, "--version"], root, true);
|
|
100
271
|
}
|
|
@@ -151,7 +322,7 @@ async function runProcess(command, args, cwd, allowFailure = false) {
|
|
|
151
322
|
});
|
|
152
323
|
child.on("error", reject);
|
|
153
324
|
child.on("close", (code) => {
|
|
154
|
-
const result = { code: code ?? 1, stdout, stderr };
|
|
325
|
+
const result = { code: code ?? 1, stdout, stderr, command: spawnSpec.command, args: spawnSpec.args, cwd: path.resolve(cwd) };
|
|
155
326
|
if ((code ?? 1) !== 0 && !allowFailure) {
|
|
156
327
|
reject(new Error(`${command} ${args.join(" ")} failed with exit code ${code ?? 1}`));
|
|
157
328
|
}
|