artifact-graph 0.9.3 → 0.10.0
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/CHANGELOG.md +28 -0
- package/dist/cli.js +1071 -75
- package/dist/index.cjs +351 -60
- package/dist/index.d.cts +32 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +331 -41
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2695,6 +2695,190 @@ var init_versioned_traceability = __esm({
|
|
|
2695
2695
|
}
|
|
2696
2696
|
});
|
|
2697
2697
|
|
|
2698
|
+
// src/native-binding-diagnostics.ts
|
|
2699
|
+
function parsePnpmVersion(stdout) {
|
|
2700
|
+
const trimmed = stdout.trim();
|
|
2701
|
+
const segments = trimmed.split(".");
|
|
2702
|
+
if (!/^\d+$/.test(segments[0] ?? "")) return void 0;
|
|
2703
|
+
const major = Number(segments[0]);
|
|
2704
|
+
const minorSegment = segments.length > 1 ? segments[1] : void 0;
|
|
2705
|
+
const minor = minorSegment !== void 0 && /^\d+$/.test(minorSegment) ? Number(minorSegment) : void 0;
|
|
2706
|
+
return minor === void 0 ? { major } : { major, minor };
|
|
2707
|
+
}
|
|
2708
|
+
function pnpmUsesAllowBuilds(version) {
|
|
2709
|
+
if (!version) return false;
|
|
2710
|
+
return version.major > 10 || version.major === 10 && (version.minor ?? 0) >= 26;
|
|
2711
|
+
}
|
|
2712
|
+
function createInstallBoundBindingLoader(installBase) {
|
|
2713
|
+
return () => (0, import_node_module.createRequire)(installBase)("better-sqlite3");
|
|
2714
|
+
}
|
|
2715
|
+
function defaultBindingLoaderImpl() {
|
|
2716
|
+
const base = typeof __filename === "string" ? __filename : import_meta.url;
|
|
2717
|
+
return (0, import_node_module.createRequire)(base)("better-sqlite3");
|
|
2718
|
+
}
|
|
2719
|
+
function defaultBindingLoader() {
|
|
2720
|
+
return defaultBindingLoaderImpl();
|
|
2721
|
+
}
|
|
2722
|
+
function classifyNativeBindingError(error, context = {}) {
|
|
2723
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2724
|
+
const code = error?.code;
|
|
2725
|
+
if (/was compiled against a different Node\.js version|NODE_MODULE_VERSION|different ABI|Incompatible ABI/i.test(
|
|
2726
|
+
message
|
|
2727
|
+
)) {
|
|
2728
|
+
return { cause: "ABI_MISMATCH", detail: message };
|
|
2729
|
+
}
|
|
2730
|
+
if (code === "MODULE_NOT_FOUND" || /Cannot find module|Cannot find package/i.test(message)) {
|
|
2731
|
+
if (context.packagePresent) {
|
|
2732
|
+
return {
|
|
2733
|
+
cause: "BUILD_DISABLED",
|
|
2734
|
+
detail: `${message}\uFF08better-sqlite3 \u5305\u76EE\u5F55\u5B58\u5728\u4F46\u539F\u751F\u4EA7\u7269\u7F3A\u5931\uFF0C\u7B26\u5408 lifecycle scripts \u88AB\u7981\u7684\u7279\u5F81\uFF09`
|
|
2735
|
+
};
|
|
2736
|
+
}
|
|
2737
|
+
return { cause: "MISSING", detail: message };
|
|
2738
|
+
}
|
|
2739
|
+
if (/Could not locate the bindings file/i.test(message)) {
|
|
2740
|
+
return {
|
|
2741
|
+
cause: "BUILD_DISABLED",
|
|
2742
|
+
detail: `${message}\uFF08better-sqlite3 \u5305\u5B58\u5728\u4F46\u539F\u751F .node \u4EA7\u7269\u672A\u6784\u5EFA\uFF0C\u7B26\u5408 lifecycle scripts \u88AB\u7981\u6216\u672A\u6784\u5EFA\u7684\u7279\u5F81\uFF09`
|
|
2743
|
+
};
|
|
2744
|
+
}
|
|
2745
|
+
if (/invalid ELF|broken binary|failed to load native/i.test(message)) {
|
|
2746
|
+
return { cause: "LOAD_ERROR", detail: message };
|
|
2747
|
+
}
|
|
2748
|
+
return { cause: "LOAD_ERROR", detail: message };
|
|
2749
|
+
}
|
|
2750
|
+
function buildNativeBindingSuggestion(cause, pnpmVersion) {
|
|
2751
|
+
const allowlist = pnpmUsesAllowBuilds(pnpmVersion) ? `pnpm 10.26+ \u5728\u9879\u76EE\u6839 pnpm-workspace.yaml \u6DFB\u52A0 allowBuilds \u952E\uFF08${PNPM_ALLOW_BUILDS_SNIPPET.replace(/\n/g, "\uFF1B")}\uFF09` : `pnpm 10.0\u201310.25 \u5728 package.json \u914D\u7F6E pnpm.onlyBuiltDependencies: ["better-sqlite3"]\uFF08pnpm 10.26+ \u6539\u7528\u9879\u76EE\u6839 pnpm-workspace.yaml \u7684 allowBuilds \u952E\uFF09`;
|
|
2752
|
+
switch (cause) {
|
|
2753
|
+
case "MISSING":
|
|
2754
|
+
return `better-sqlite3 \u539F\u751F\u4EA7\u7269\u7F3A\u5931\u3002\u6309 INSTALL.md \u58F0\u660E\u6784\u5EFA\u5141\u8BB8\u6E05\u5355\u540E\u91CD\u65B0\u5B89\u88C5\uFF1A${allowlist}\uFF0C\u7136\u540E pnpm install\u3002`;
|
|
2755
|
+
case "ABI_MISMATCH":
|
|
2756
|
+
return `\u5F53\u524D Node ABI \u4E0E better-sqlite3 prebuilt \u76EE\u6807\u4E0D\u4E00\u81F4\uFF08\u5F53\u524D process.versions.modules=${process.versions.modules}\uFF09\u3002\u5207\u6362\u5230\u4E0E\u5DF2\u5B89\u88C5 prebuilt \u5339\u914D\u7684 Node \u7248\u672C\uFF0C\u6216\u5BF9\u5F53\u524D Node \u91CD\u5EFA\uFF1Apnpm rebuild better-sqlite3\u3002\u4E0D\u8981\u624B\u5DE5\u7F16\u8BD1\u3002`;
|
|
2757
|
+
case "BUILD_DISABLED":
|
|
2758
|
+
return `pnpm lifecycle scripts \u88AB\u7981\u5BFC\u81F4 better-sqlite3 \u672A\u6784\u5EFA\u3002${allowlist}\uFF0C\u7136\u540E pnpm install \u91CD\u5EFA\u539F\u751F\u4EA7\u7269\u3002\u4E0D\u8981\u624B\u5DE5\u7F16\u8BD1\u3002`;
|
|
2759
|
+
default:
|
|
2760
|
+
return "better-sqlite3 \u52A0\u8F7D\u5931\u8D25\uFF08\u672A\u77E5\u539F\u751F\u9519\u8BEF\uFF09\u3002\u5148\u8FD0\u884C artifact-graph doctor --format json \u67E5\u770B\u63A2\u9488\u8BE6\u60C5\uFF0C\u518D\u6309 INSTALL.md \u91CD\u5EFA\u5F53\u524D\u9009\u4E2D\u8FD0\u884C\u65F6\u7684\u539F\u751F\u4EA7\u7269\u3002";
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
function probeNativeBinding(context = {}) {
|
|
2764
|
+
const loader = context.loader ?? defaultBindingLoader;
|
|
2765
|
+
const presenceRoot = context.installRoot ?? context.root;
|
|
2766
|
+
const packagePresent = presenceRoot ? betterSqlite3PackagePresent(presenceRoot) : void 0;
|
|
2767
|
+
const classify = (error) => classifyNativeBindingError(error, { packagePresent });
|
|
2768
|
+
const fail = (failedStage, error) => {
|
|
2769
|
+
const { cause, detail } = classify(error);
|
|
2770
|
+
return { ok: false, failedStage, cause, detail, suggestion: buildNativeBindingSuggestion(cause, context.pnpmVersion) };
|
|
2771
|
+
};
|
|
2772
|
+
let DatabaseCtor;
|
|
2773
|
+
try {
|
|
2774
|
+
DatabaseCtor = loader();
|
|
2775
|
+
} catch (error) {
|
|
2776
|
+
return fail("load", error);
|
|
2777
|
+
}
|
|
2778
|
+
const Database = DatabaseCtor;
|
|
2779
|
+
let db;
|
|
2780
|
+
try {
|
|
2781
|
+
db = new Database(":memory:");
|
|
2782
|
+
} catch (error) {
|
|
2783
|
+
return fail("open", error);
|
|
2784
|
+
}
|
|
2785
|
+
try {
|
|
2786
|
+
db.exec("CREATE TABLE probe (id INTEGER PRIMARY KEY, value TEXT)");
|
|
2787
|
+
db.prepare("INSERT INTO probe (id, value) VALUES (?, ?)").run(1, "ok");
|
|
2788
|
+
} catch (error) {
|
|
2789
|
+
safeClose(db);
|
|
2790
|
+
return fail("write", error);
|
|
2791
|
+
}
|
|
2792
|
+
try {
|
|
2793
|
+
const row = db.prepare("SELECT value FROM probe WHERE id = ?").get(1);
|
|
2794
|
+
if (!row || row.value !== "ok") {
|
|
2795
|
+
safeClose(db);
|
|
2796
|
+
return {
|
|
2797
|
+
ok: false,
|
|
2798
|
+
failedStage: "read",
|
|
2799
|
+
cause: "LOAD_ERROR",
|
|
2800
|
+
detail: "probe \u56DE\u8BFB\u65AD\u8A00\u5931\u8D25\uFF1ASELECT \u7ED3\u679C\u4E0E\u5199\u5165\u503C\u4E0D\u4E00\u81F4\u3002",
|
|
2801
|
+
suggestion: buildNativeBindingSuggestion("LOAD_ERROR", context.pnpmVersion)
|
|
2802
|
+
};
|
|
2803
|
+
}
|
|
2804
|
+
} catch (error) {
|
|
2805
|
+
safeClose(db);
|
|
2806
|
+
return fail("read", error);
|
|
2807
|
+
}
|
|
2808
|
+
try {
|
|
2809
|
+
db.close();
|
|
2810
|
+
} catch (error) {
|
|
2811
|
+
return fail("close", error);
|
|
2812
|
+
}
|
|
2813
|
+
return { ok: true };
|
|
2814
|
+
}
|
|
2815
|
+
function buildNativeBindingDiagnostic(failure, probeContext) {
|
|
2816
|
+
return {
|
|
2817
|
+
selectedCli: probeContext.selectedCli,
|
|
2818
|
+
runtime: `${process.execPath} (v${process.versions.node})`,
|
|
2819
|
+
abi: `process.versions.modules=${process.versions.modules}${abiPrebuiltHint(failure.detail)}`,
|
|
2820
|
+
installSource: probeContext.installSource,
|
|
2821
|
+
probedFrom: probeContext.probedFrom,
|
|
2822
|
+
failedStage: failure.failedStage,
|
|
2823
|
+
cause: failure.cause,
|
|
2824
|
+
suggestion: failure.suggestion
|
|
2825
|
+
};
|
|
2826
|
+
}
|
|
2827
|
+
function buildNativeBindingSuccessDiagnostic(probeContext) {
|
|
2828
|
+
return {
|
|
2829
|
+
selectedCli: probeContext.selectedCli,
|
|
2830
|
+
runtime: `${process.execPath} (v${process.versions.node})`,
|
|
2831
|
+
installSource: probeContext.installSource,
|
|
2832
|
+
probedFrom: probeContext.probedFrom
|
|
2833
|
+
};
|
|
2834
|
+
}
|
|
2835
|
+
function findPackageRoot(anchorFile) {
|
|
2836
|
+
let dir = (0, import_node_path4.dirname)(anchorFile);
|
|
2837
|
+
for (; ; ) {
|
|
2838
|
+
if ((0, import_node_fs2.existsSync)((0, import_node_path4.join)(dir, "package.json"))) return dir;
|
|
2839
|
+
const parent = (0, import_node_path4.dirname)(dir);
|
|
2840
|
+
if (parent === dir) return void 0;
|
|
2841
|
+
dir = parent;
|
|
2842
|
+
}
|
|
2843
|
+
}
|
|
2844
|
+
function safeClose(db) {
|
|
2845
|
+
try {
|
|
2846
|
+
db?.close();
|
|
2847
|
+
} catch {
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
function abiPrebuiltHint(detail) {
|
|
2851
|
+
const match = /using NODE_MODULE_VERSION (\d+)/.exec(detail);
|
|
2852
|
+
return match ? `\uFF1Bprebuilt \u76EE\u6807 NODE_MODULE_VERSION=${match[1]}` : "";
|
|
2853
|
+
}
|
|
2854
|
+
function betterSqlite3PackagePresent(root) {
|
|
2855
|
+
const direct = (0, import_node_path4.join)(root, "node_modules", "better-sqlite3", "package.json");
|
|
2856
|
+
if ((0, import_node_fs2.existsSync)(direct)) return true;
|
|
2857
|
+
const pnpmDir = (0, import_node_path4.join)(root, "node_modules", ".pnpm");
|
|
2858
|
+
let entries;
|
|
2859
|
+
try {
|
|
2860
|
+
entries = (0, import_node_fs2.readdirSync)(pnpmDir);
|
|
2861
|
+
} catch {
|
|
2862
|
+
return false;
|
|
2863
|
+
}
|
|
2864
|
+
return entries.some((entry) => {
|
|
2865
|
+
if (!entry.startsWith("better-sqlite3@")) return false;
|
|
2866
|
+
return (0, import_node_fs2.existsSync)((0, import_node_path4.join)(pnpmDir, entry, "node_modules", "better-sqlite3", "package.json"));
|
|
2867
|
+
});
|
|
2868
|
+
}
|
|
2869
|
+
var import_node_fs2, import_node_module, import_node_path4, import_node_url, import_meta, PNPM_ALLOW_BUILDS_SNIPPET;
|
|
2870
|
+
var init_native_binding_diagnostics = __esm({
|
|
2871
|
+
"src/native-binding-diagnostics.ts"() {
|
|
2872
|
+
"use strict";
|
|
2873
|
+
import_node_fs2 = require("fs");
|
|
2874
|
+
import_node_module = require("module");
|
|
2875
|
+
import_node_path4 = require("path");
|
|
2876
|
+
import_node_url = require("url");
|
|
2877
|
+
import_meta = {};
|
|
2878
|
+
PNPM_ALLOW_BUILDS_SNIPPET = "pnpm-workspace.yaml:\nallowBuilds:\n better-sqlite3: true";
|
|
2879
|
+
}
|
|
2880
|
+
});
|
|
2881
|
+
|
|
2698
2882
|
// src/cli-resolver.ts
|
|
2699
2883
|
async function resolveArtifactGraphCli(root, options = {}) {
|
|
2700
2884
|
const pathCli = await findCommandOnPath("artifact-graph");
|
|
@@ -2702,7 +2886,7 @@ async function resolveArtifactGraphCli(root, options = {}) {
|
|
|
2702
2886
|
const candidates = [
|
|
2703
2887
|
{
|
|
2704
2888
|
source: "node_modules",
|
|
2705
|
-
path: (0,
|
|
2889
|
+
path: (0, import_node_path5.join)(root, "node_modules/.bin/artifact-graph"),
|
|
2706
2890
|
exists: false
|
|
2707
2891
|
},
|
|
2708
2892
|
{
|
|
@@ -2735,13 +2919,33 @@ async function resolveArtifactGraphCli(root, options = {}) {
|
|
|
2735
2919
|
}
|
|
2736
2920
|
async function doctorArtifactChain(root, options = {}) {
|
|
2737
2921
|
const cli = await resolveArtifactGraphCli(root, options);
|
|
2738
|
-
const configPath = (0,
|
|
2739
|
-
const lockPath = (0,
|
|
2922
|
+
const configPath = (0, import_node_path5.join)(root, "artifact-graph.config.yaml");
|
|
2923
|
+
const lockPath = (0, import_node_path5.join)(root, VERSION_LOCK_PATH);
|
|
2740
2924
|
const supportedCommands = cli.path ? await detectSupportedCommands(cli.path) : [];
|
|
2741
2925
|
const nodeCompatible = isNodeCompatible(process.versions.node);
|
|
2926
|
+
const pnpmVersion = await detectPnpmVersion();
|
|
2927
|
+
const installBase = bindingInstallBase(cli, root);
|
|
2928
|
+
const installRoot = bindingInstallRoot(cli, root);
|
|
2929
|
+
const loader = options.bindingLoader ?? (installBase ? createInstallBoundBindingLoader(installBase) : void 0);
|
|
2930
|
+
const probe = probeNativeBinding({
|
|
2931
|
+
root,
|
|
2932
|
+
...installRoot ? { installRoot } : {},
|
|
2933
|
+
pnpmVersion,
|
|
2934
|
+
...loader ? { loader } : {}
|
|
2935
|
+
});
|
|
2936
|
+
const probedFrom = installBase ?? "(current artifact-graph package)";
|
|
2937
|
+
const probeContext = {
|
|
2938
|
+
selectedCli: cli.path ? `${cli.path} (${cli.source})` : "not found",
|
|
2939
|
+
installSource: cli.source ?? "unknown",
|
|
2940
|
+
probedFrom
|
|
2941
|
+
};
|
|
2942
|
+
const nativeBinding = probe.ok ? { ok: true, ...buildNativeBindingSuccessDiagnostic(probeContext) } : { ok: false, ...buildNativeBindingDiagnostic(probe, probeContext) };
|
|
2742
2943
|
const warnings = [
|
|
2743
2944
|
...cli.warnings,
|
|
2744
|
-
...nodeCompatible ? [] : [`Node.js ${process.versions.node} does not satisfy >=22.0.0.`]
|
|
2945
|
+
...nodeCompatible ? [] : [`Node.js ${process.versions.node} does not satisfy >=22.0.0.`],
|
|
2946
|
+
...probe.ok ? [] : [
|
|
2947
|
+
`better-sqlite3 binding probe FAILED at stage "${probe.failedStage}" (cause ${probe.cause}): ${probe.suggestion}`
|
|
2948
|
+
]
|
|
2745
2949
|
];
|
|
2746
2950
|
return {
|
|
2747
2951
|
schemaVersion: "1.0",
|
|
@@ -2760,6 +2964,7 @@ async function doctorArtifactChain(root, options = {}) {
|
|
|
2760
2964
|
path: lockPath,
|
|
2761
2965
|
exists: await pathExists(lockPath)
|
|
2762
2966
|
},
|
|
2967
|
+
nativeBinding,
|
|
2763
2968
|
supportedCommands,
|
|
2764
2969
|
warnings
|
|
2765
2970
|
};
|
|
@@ -2775,6 +2980,31 @@ function renderDoctorMarkdown(report) {
|
|
|
2775
2980
|
`Lock: \`${report.lock.path}\` ${report.lock.exists ? "found" : "missing"}`,
|
|
2776
2981
|
""
|
|
2777
2982
|
];
|
|
2983
|
+
lines.push("## Native Binding Probe");
|
|
2984
|
+
if (report.nativeBinding.ok) {
|
|
2985
|
+
const binding = report.nativeBinding;
|
|
2986
|
+
lines.push(
|
|
2987
|
+
"- better-sqlite3 probe: PASS",
|
|
2988
|
+
` - selectedCli: \`${binding.selectedCli}\``,
|
|
2989
|
+
` - runtime: \`${binding.runtime}\``,
|
|
2990
|
+
` - installSource: \`${binding.installSource}\``,
|
|
2991
|
+
` - probedFrom: \`${binding.probedFrom}\``
|
|
2992
|
+
);
|
|
2993
|
+
} else {
|
|
2994
|
+
const binding = report.nativeBinding;
|
|
2995
|
+
lines.push(
|
|
2996
|
+
"- better-sqlite3 probe: **FAIL**",
|
|
2997
|
+
` - failedStage: \`${binding.failedStage}\``,
|
|
2998
|
+
` - cause: \`${binding.cause}\``,
|
|
2999
|
+
` - selectedCli: \`${binding.selectedCli}\``,
|
|
3000
|
+
` - runtime: \`${binding.runtime}\``,
|
|
3001
|
+
` - abi: \`${binding.abi}\``,
|
|
3002
|
+
` - installSource: \`${binding.installSource}\``,
|
|
3003
|
+
` - probedFrom: \`${binding.probedFrom}\``,
|
|
3004
|
+
` - suggestion: ${binding.suggestion}`
|
|
3005
|
+
);
|
|
3006
|
+
}
|
|
3007
|
+
lines.push("");
|
|
2778
3008
|
if (report.supportedCommands.length > 0) {
|
|
2779
3009
|
lines.push("## Supported Commands");
|
|
2780
3010
|
for (const command of report.supportedCommands) {
|
|
@@ -2809,7 +3039,7 @@ ${maybe.stderr ?? ""}`;
|
|
|
2809
3039
|
}
|
|
2810
3040
|
async function pathExists(path) {
|
|
2811
3041
|
try {
|
|
2812
|
-
await (0, import_promises4.access)(path,
|
|
3042
|
+
await (0, import_promises4.access)(path, import_node_fs3.constants.R_OK);
|
|
2813
3043
|
return true;
|
|
2814
3044
|
} catch {
|
|
2815
3045
|
return false;
|
|
@@ -2825,22 +3055,82 @@ async function findCommandOnPath(command) {
|
|
|
2825
3055
|
}
|
|
2826
3056
|
}
|
|
2827
3057
|
function resolveCandidatePath(root, candidatePath) {
|
|
2828
|
-
return (0,
|
|
3058
|
+
return (0, import_node_path5.isAbsolute)(candidatePath) ? candidatePath : (0, import_node_path5.resolve)(root, candidatePath);
|
|
2829
3059
|
}
|
|
2830
3060
|
function isNodeCompatible(version) {
|
|
2831
3061
|
const major = Number(version.split(".")[0]);
|
|
2832
3062
|
return Number.isFinite(major) && major >= 22;
|
|
2833
3063
|
}
|
|
2834
|
-
|
|
3064
|
+
async function detectPnpmVersion() {
|
|
3065
|
+
try {
|
|
3066
|
+
const result = await execFileAsync("pnpm", ["--version"]);
|
|
3067
|
+
return parsePnpmVersion(result.stdout);
|
|
3068
|
+
} catch {
|
|
3069
|
+
return void 0;
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
function bindingInstallBase(cli, root) {
|
|
3073
|
+
if (!cli.path || !cli.source) return void 0;
|
|
3074
|
+
switch (cli.source) {
|
|
3075
|
+
case "node_modules":
|
|
3076
|
+
return (0, import_node_path5.join)(root, "package.json");
|
|
3077
|
+
case "plugin-bundled":
|
|
3078
|
+
case "path":
|
|
3079
|
+
case "legacy":
|
|
3080
|
+
return resolveCliInstallAnchor(cli.path);
|
|
3081
|
+
default:
|
|
3082
|
+
return void 0;
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
function bindingInstallRoot(cli, root) {
|
|
3086
|
+
if (!cli.path || !cli.source) return void 0;
|
|
3087
|
+
switch (cli.source) {
|
|
3088
|
+
case "node_modules":
|
|
3089
|
+
return root;
|
|
3090
|
+
case "plugin-bundled":
|
|
3091
|
+
case "path":
|
|
3092
|
+
case "legacy":
|
|
3093
|
+
return findPackageRoot(resolveCliInstallAnchor(cli.path));
|
|
3094
|
+
default:
|
|
3095
|
+
return void 0;
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
3098
|
+
function resolveCliInstallAnchor(cliPath) {
|
|
3099
|
+
const real = safeRealpath(cliPath);
|
|
3100
|
+
if ((0, import_node_path5.basename)((0, import_node_path5.dirname)(real)) !== ".bin") return real;
|
|
3101
|
+
const shimTarget = readBinShimTarget(real);
|
|
3102
|
+
return shimTarget ? safeRealpath(shimTarget) : real;
|
|
3103
|
+
}
|
|
3104
|
+
function readBinShimTarget(shimPath) {
|
|
3105
|
+
let content;
|
|
3106
|
+
try {
|
|
3107
|
+
content = (0, import_node_fs3.readFileSync)(shimPath, "utf-8");
|
|
3108
|
+
} catch {
|
|
3109
|
+
return void 0;
|
|
3110
|
+
}
|
|
3111
|
+
if (!content.startsWith("#!")) return void 0;
|
|
3112
|
+
const match = /\$basedir\/(\.\.(?:\/[^"'\s]+)+\.js)/.exec(content);
|
|
3113
|
+
if (!match) return void 0;
|
|
3114
|
+
return (0, import_node_path5.resolve)((0, import_node_path5.dirname)(shimPath), match[1]);
|
|
3115
|
+
}
|
|
3116
|
+
function safeRealpath(path) {
|
|
3117
|
+
try {
|
|
3118
|
+
return (0, import_node_fs3.realpathSync)(path);
|
|
3119
|
+
} catch {
|
|
3120
|
+
return path;
|
|
3121
|
+
}
|
|
3122
|
+
}
|
|
3123
|
+
var import_node_child_process, import_node_fs3, import_promises4, import_node_path5, import_node_util, execFileAsync, KNOWN_COMMANDS;
|
|
2835
3124
|
var init_cli_resolver = __esm({
|
|
2836
3125
|
"src/cli-resolver.ts"() {
|
|
2837
3126
|
"use strict";
|
|
2838
3127
|
import_node_child_process = require("child_process");
|
|
2839
|
-
|
|
3128
|
+
import_node_fs3 = require("fs");
|
|
2840
3129
|
import_promises4 = require("fs/promises");
|
|
2841
|
-
|
|
3130
|
+
import_node_path5 = require("path");
|
|
2842
3131
|
import_node_util = require("util");
|
|
2843
3132
|
init_versioned_traceability();
|
|
3133
|
+
init_native_binding_diagnostics();
|
|
2844
3134
|
execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
2845
3135
|
KNOWN_COMMANDS = [
|
|
2846
3136
|
"init",
|
|
@@ -2859,6 +3149,7 @@ var init_cli_resolver = __esm({
|
|
|
2859
3149
|
"version-lock refresh",
|
|
2860
3150
|
"trace-version",
|
|
2861
3151
|
"next-id",
|
|
3152
|
+
"refactor-id",
|
|
2862
3153
|
"render",
|
|
2863
3154
|
"doctor"
|
|
2864
3155
|
];
|
|
@@ -2949,14 +3240,14 @@ async function resolveGitHookPath(root, hookName) {
|
|
|
2949
3240
|
]);
|
|
2950
3241
|
const value = stdout.trim();
|
|
2951
3242
|
if (!value) throw new Error(`Git returned an empty hook path for ${hookName}`);
|
|
2952
|
-
return (0,
|
|
3243
|
+
return (0, import_node_path6.isAbsolute)(value) ? (0, import_node_path6.resolve)(value) : (0, import_node_path6.resolve)(root, value);
|
|
2953
3244
|
}
|
|
2954
|
-
var import_node_child_process3,
|
|
3245
|
+
var import_node_child_process3, import_node_path6, import_node_util3, execFileAsync3;
|
|
2955
3246
|
var init_git_hook_path = __esm({
|
|
2956
3247
|
"src/git-hook-path.ts"() {
|
|
2957
3248
|
"use strict";
|
|
2958
3249
|
import_node_child_process3 = require("child_process");
|
|
2959
|
-
|
|
3250
|
+
import_node_path6 = require("path");
|
|
2960
3251
|
import_node_util3 = require("util");
|
|
2961
3252
|
execFileAsync3 = (0, import_node_util3.promisify)(import_node_child_process3.execFile);
|
|
2962
3253
|
}
|
|
@@ -3211,7 +3502,7 @@ async function readHookSnapshot(hookPath) {
|
|
|
3211
3502
|
}
|
|
3212
3503
|
let handle;
|
|
3213
3504
|
try {
|
|
3214
|
-
handle = await (0, import_promises5.open)(hookPath,
|
|
3505
|
+
handle = await (0, import_promises5.open)(hookPath, import_node_fs4.constants.O_RDONLY | (import_node_fs4.constants.O_NOFOLLOW ?? 0));
|
|
3215
3506
|
const opened = await handle.stat({ bigint: true });
|
|
3216
3507
|
if (opened.dev !== metadata.dev || opened.ino !== metadata.ino) {
|
|
3217
3508
|
await handle.close();
|
|
@@ -3273,8 +3564,8 @@ async function removeHookAtomically(hookPath, snapshot) {
|
|
|
3273
3564
|
}
|
|
3274
3565
|
}
|
|
3275
3566
|
async function writeHookAtomically(hookPath, content, snapshot, mode) {
|
|
3276
|
-
await (0, import_promises5.mkdir)((0,
|
|
3277
|
-
const temporaryPath = (0,
|
|
3567
|
+
await (0, import_promises5.mkdir)((0, import_node_path7.dirname)(hookPath), { recursive: true });
|
|
3568
|
+
const temporaryPath = (0, import_node_path7.join)((0, import_node_path7.dirname)(hookPath), `.${(0, import_node_path7.basename)(hookPath)}.${(0, import_node_crypto2.randomUUID)()}.tmp`);
|
|
3278
3569
|
let temporaryExists = false;
|
|
3279
3570
|
try {
|
|
3280
3571
|
const temporary = await (0, import_promises5.open)(temporaryPath, "wx", mode);
|
|
@@ -3320,14 +3611,14 @@ function findManagedRange(content, begin, end) {
|
|
|
3320
3611
|
end: endLine < 0 ? content.length : endLine + 1
|
|
3321
3612
|
};
|
|
3322
3613
|
}
|
|
3323
|
-
var
|
|
3614
|
+
var import_node_fs4, import_node_crypto2, import_promises5, import_node_path7, DEFAULT_MARKER_ID, MANAGED_STATE_PREFIX, UnsupportedHookInterpreterError, SymlinkHookUnsupportedError, UnsupportedHookTypeError, InvalidManagedHookStateError, ConcurrentHookModificationError, HookTransactionRollbackError;
|
|
3324
3615
|
var init_hook_installer = __esm({
|
|
3325
3616
|
"src/hook-installer.ts"() {
|
|
3326
3617
|
"use strict";
|
|
3327
|
-
|
|
3618
|
+
import_node_fs4 = require("fs");
|
|
3328
3619
|
import_node_crypto2 = require("crypto");
|
|
3329
3620
|
import_promises5 = require("fs/promises");
|
|
3330
|
-
|
|
3621
|
+
import_node_path7 = require("path");
|
|
3331
3622
|
DEFAULT_MARKER_ID = "artifact-chain-assistant";
|
|
3332
3623
|
MANAGED_STATE_PREFIX = "# artifact-chain-assistant managed state v1:";
|
|
3333
3624
|
UnsupportedHookInterpreterError = class extends Error {
|
|
@@ -4045,7 +4336,7 @@ async function loadContractsFromDirectory(contractsDir, options) {
|
|
|
4045
4336
|
const entries = await (0, import_promises6.readdir)(contractsDir, { withFileTypes: true });
|
|
4046
4337
|
for (const entry of entries) {
|
|
4047
4338
|
if (entry.isDirectory()) {
|
|
4048
|
-
const schemaPath = (0,
|
|
4339
|
+
const schemaPath = (0, import_node_path8.join)(contractsDir, entry.name, "schema.json");
|
|
4049
4340
|
const contract = await loadContract(schemaPath, options);
|
|
4050
4341
|
contracts.push(contract);
|
|
4051
4342
|
}
|
|
@@ -4160,13 +4451,13 @@ async function loadContractCatalog(contractsDir, options) {
|
|
|
4160
4451
|
}
|
|
4161
4452
|
return catalog;
|
|
4162
4453
|
}
|
|
4163
|
-
var import_node_crypto3, import_promises6,
|
|
4454
|
+
var import_node_crypto3, import_promises6, import_node_path8, import_ajv, CONTRACT_ERROR_CODES, ContractError, OFFICIAL_AUTHORITY, OFFICIAL_NAMESPACE_PATTERN, ContractRegistry, _validatorCache, E2E_NORMALIZER_CONFIG, ContractCatalog;
|
|
4164
4455
|
var init_contract_kernel = __esm({
|
|
4165
4456
|
"src/contract-kernel.ts"() {
|
|
4166
4457
|
"use strict";
|
|
4167
4458
|
import_node_crypto3 = require("crypto");
|
|
4168
4459
|
import_promises6 = require("fs/promises");
|
|
4169
|
-
|
|
4460
|
+
import_node_path8 = require("path");
|
|
4170
4461
|
import_ajv = __toESM(require("ajv"), 1);
|
|
4171
4462
|
CONTRACT_ERROR_CODES = {
|
|
4172
4463
|
/** Contract identity not found */
|
|
@@ -4519,11 +4810,11 @@ __export(index_exports, {
|
|
|
4519
4810
|
collectChangedPaths: () => collectChangedPaths,
|
|
4520
4811
|
computeE2eCoverageStats: () => computeE2eCoverageStats,
|
|
4521
4812
|
computeRevisionDigest: () => computeRevisionDigest,
|
|
4522
|
-
dirname: () =>
|
|
4813
|
+
dirname: () => import_node_path9.dirname,
|
|
4523
4814
|
discoverAndAuditPackets: () => discoverAndAuditPackets,
|
|
4524
4815
|
discoverTargets: () => discoverTargets,
|
|
4525
4816
|
doctorArtifactChain: () => doctorArtifactChain,
|
|
4526
|
-
extname: () =>
|
|
4817
|
+
extname: () => import_node_path9.extname,
|
|
4527
4818
|
formatContextMarkdown: () => formatContextMarkdown,
|
|
4528
4819
|
generateE2eRegistry: () => generateE2eRegistry,
|
|
4529
4820
|
getArtifactTypeMetadata: () => getArtifactTypeMetadata,
|
|
@@ -4620,7 +4911,7 @@ function resolveArtifactTypeName(schema, token) {
|
|
|
4620
4911
|
return void 0;
|
|
4621
4912
|
}
|
|
4622
4913
|
async function loadConfig(root) {
|
|
4623
|
-
const configPath = (0,
|
|
4914
|
+
const configPath = (0, import_node_path9.join)(root, "artifact-graph.config.yaml");
|
|
4624
4915
|
let parsed = {};
|
|
4625
4916
|
try {
|
|
4626
4917
|
const raw = await (0, import_promises7.readFile)(configPath, "utf-8");
|
|
@@ -4713,7 +5004,7 @@ function validateE2eConfig(e2e) {
|
|
|
4713
5004
|
if (typeof runner.root !== "string" || !runner.root.trim()) {
|
|
4714
5005
|
throw new Error(`Invalid e2e.runners[${runner.name}].root: must be a non-empty string.`);
|
|
4715
5006
|
}
|
|
4716
|
-
if ((0,
|
|
5007
|
+
if ((0, import_node_path9.isAbsolute)(runner.root)) {
|
|
4717
5008
|
throw new Error(`Invalid e2e.runners[${runner.name}].root: "${runner.root}" must not be an absolute path.`);
|
|
4718
5009
|
}
|
|
4719
5010
|
if (runner.root.replace(/\\/g, "/").split("/").includes("..")) {
|
|
@@ -4797,14 +5088,14 @@ async function scanArtifacts(root, schema) {
|
|
|
4797
5088
|
continue;
|
|
4798
5089
|
}
|
|
4799
5090
|
scannedFiles.set(file, type);
|
|
4800
|
-
const raw = await (0, import_promises7.readFile)((0,
|
|
5091
|
+
const raw = await (0, import_promises7.readFile)((0, import_node_path9.join)(root, file), "utf-8");
|
|
4801
5092
|
const parsed = parseFile(type, file, raw, config);
|
|
4802
5093
|
nodes.push(...parsed.nodes);
|
|
4803
5094
|
edges.push(...parsed.edges);
|
|
4804
5095
|
scanDiagnostics.push(...parsed.diagnostics);
|
|
4805
5096
|
}
|
|
4806
5097
|
}
|
|
4807
|
-
const absoluteRoot = (0,
|
|
5098
|
+
const absoluteRoot = (0, import_node_path9.isAbsolute)(root) ? root : (0, import_node_path9.resolve)(root);
|
|
4808
5099
|
const graph = buildGraph(nodes, edges, scanDiagnostics, absoluteRoot);
|
|
4809
5100
|
return resolveMatrixEdges(graph);
|
|
4810
5101
|
}
|
|
@@ -5113,7 +5404,7 @@ async function validateScenarioPrdLinkIndex(root, graph) {
|
|
|
5113
5404
|
const indexPath = "artifacts/prd/feature-index.md";
|
|
5114
5405
|
let raw = "";
|
|
5115
5406
|
try {
|
|
5116
|
-
raw = await (0, import_promises7.readFile)((0,
|
|
5407
|
+
raw = await (0, import_promises7.readFile)((0, import_node_path9.join)(root, indexPath), "utf-8");
|
|
5117
5408
|
} catch (error) {
|
|
5118
5409
|
if (error.code === "ENOENT") {
|
|
5119
5410
|
return [];
|
|
@@ -5303,11 +5594,12 @@ function nextId(graph, schema, type, rangeName) {
|
|
|
5303
5594
|
throw new Error(`ID range ${type}.${rangeName} is exhausted`);
|
|
5304
5595
|
}
|
|
5305
5596
|
async function writeGraphCache(root, graph) {
|
|
5306
|
-
const cacheDir = (0,
|
|
5597
|
+
const cacheDir = (0, import_node_path9.join)(root, ".artifact-graph");
|
|
5307
5598
|
await (0, import_promises7.mkdir)(cacheDir, { recursive: true });
|
|
5308
|
-
await (0, import_promises7.writeFile)((0,
|
|
5599
|
+
await (0, import_promises7.writeFile)((0, import_node_path9.join)(cacheDir, "index.json"), `${JSON.stringify(graph, null, 2)}
|
|
5309
5600
|
`);
|
|
5310
|
-
const
|
|
5601
|
+
const { default: Database } = await import("better-sqlite3");
|
|
5602
|
+
const db = new Database((0, import_node_path9.join)(cacheDir, "graph.sqlite"));
|
|
5311
5603
|
try {
|
|
5312
5604
|
db.exec(`
|
|
5313
5605
|
DROP TABLE IF EXISTS nodes;
|
|
@@ -5418,7 +5710,7 @@ function parseFile(type, path, raw, schema = DEFAULT_SCHEMA) {
|
|
|
5418
5710
|
}
|
|
5419
5711
|
function parseGenericMarkdown(type, path, raw, schema) {
|
|
5420
5712
|
const diagnostics = [];
|
|
5421
|
-
const ext = (0,
|
|
5713
|
+
const ext = (0, import_node_path9.extname)(path).toLowerCase();
|
|
5422
5714
|
if (ext !== ".md" && ext !== ".markdown") {
|
|
5423
5715
|
diagnostics.push(issue(
|
|
5424
5716
|
"UNSUPPORTED_FORMAT",
|
|
@@ -5661,7 +5953,7 @@ function parseDecisions(path, raw) {
|
|
|
5661
5953
|
}
|
|
5662
5954
|
function isTestFile(filePath) {
|
|
5663
5955
|
const normalized = filePath.replace(/\\/g, "/");
|
|
5664
|
-
const name = (0,
|
|
5956
|
+
const name = (0, import_node_path9.basename)(normalized);
|
|
5665
5957
|
if (/\.(test|spec)\.[^.]+$/.test(name)) return true;
|
|
5666
5958
|
if (/(^|\/)(tests|test|__tests__)\//.test(normalized)) return true;
|
|
5667
5959
|
if (/\w+Tests?\.java$/.test(name)) return true;
|
|
@@ -5982,7 +6274,7 @@ function parseE2eTest(path, raw) {
|
|
|
5982
6274
|
});
|
|
5983
6275
|
const nodes = [];
|
|
5984
6276
|
const edges = [];
|
|
5985
|
-
const batch = String(data.test_batch ?? (0,
|
|
6277
|
+
const batch = String(data.test_batch ?? (0, import_node_path9.basename)(path, (0, import_node_path9.extname)(path))).trim();
|
|
5986
6278
|
const frontmatterScenarios = toArray(data.related_scenarios).map((value) => String(value).trim()).filter(Boolean);
|
|
5987
6279
|
const scopeFeatures = extractCodes(String(data.scope ?? ""), "feature");
|
|
5988
6280
|
const frontmatterFeatures = [.../* @__PURE__ */ new Set([...Object.keys(asRecord(data.ac_coverage)), ...scopeFeatures])];
|
|
@@ -6055,7 +6347,7 @@ function parseE2eRegistry(path, raw) {
|
|
|
6055
6347
|
data = { parseError: error.message };
|
|
6056
6348
|
}
|
|
6057
6349
|
return {
|
|
6058
|
-
nodes: [{ type: "e2e_registry", code: (0,
|
|
6350
|
+
nodes: [{ type: "e2e_registry", code: (0, import_node_path9.basename)(path, (0, import_node_path9.extname)(path)), title: "E2E Test Registry", path, line: 1, attrs: data }],
|
|
6059
6351
|
edges: []
|
|
6060
6352
|
};
|
|
6061
6353
|
}
|
|
@@ -7081,10 +7373,10 @@ function validateE2eRegistry(graph) {
|
|
|
7081
7373
|
async function validateExecutableTraceability(root, config) {
|
|
7082
7374
|
const issues = [];
|
|
7083
7375
|
const schema = config ?? await loadConfig(root);
|
|
7084
|
-
const e2eDir = (0,
|
|
7376
|
+
const e2eDir = (0, import_node_path9.join)(root, "artifacts", "tests", "e2e");
|
|
7085
7377
|
let e2eFiles;
|
|
7086
7378
|
try {
|
|
7087
|
-
e2eFiles = (await (0, import_promises7.readdir)(e2eDir)).filter((name) => /^test-.*\.md$/.test(name)).map((name) => (0,
|
|
7379
|
+
e2eFiles = (await (0, import_promises7.readdir)(e2eDir)).filter((name) => /^test-.*\.md$/.test(name)).map((name) => (0, import_node_path9.join)(e2eDir, name));
|
|
7088
7380
|
} catch {
|
|
7089
7381
|
return [];
|
|
7090
7382
|
}
|
|
@@ -7094,10 +7386,10 @@ async function validateExecutableTraceability(root, config) {
|
|
|
7094
7386
|
const mdBatches = /* @__PURE__ */ new Set();
|
|
7095
7387
|
for (const filePath of e2eFiles) {
|
|
7096
7388
|
const raw = await (0, import_promises7.readFile)(filePath, "utf-8");
|
|
7097
|
-
const relPath = (0,
|
|
7389
|
+
const relPath = (0, import_node_path9.relative)(root, filePath).split("\\").join("/");
|
|
7098
7390
|
const parsed = (0, import_gray_matter.default)(raw);
|
|
7099
7391
|
const data = parsed.data;
|
|
7100
|
-
const batch = String(data.test_batch ?? (0,
|
|
7392
|
+
const batch = String(data.test_batch ?? (0, import_node_path9.basename)(filePath, (0, import_node_path9.extname)(filePath))).trim();
|
|
7101
7393
|
const lines = raw.split(/\r?\n/);
|
|
7102
7394
|
const tcStarts = [];
|
|
7103
7395
|
lines.forEach((line, index) => {
|
|
@@ -7142,7 +7434,7 @@ async function validateExecutableTraceability(root, config) {
|
|
|
7142
7434
|
const tcAnnotationRegex = /\/\/!?\s*@(?:e2e_test|tc)\s+(\S+?)\s+\[(\w+)\]/;
|
|
7143
7435
|
const tcAnnotationNoLevelRegex = /\/\/!?\s*@(?:e2e_test|tc)\s+(\S+)/;
|
|
7144
7436
|
for (const specFile of specFiles) {
|
|
7145
|
-
const fullSpecPath = (0,
|
|
7437
|
+
const fullSpecPath = (0, import_node_path9.join)(root, specFile);
|
|
7146
7438
|
let content;
|
|
7147
7439
|
try {
|
|
7148
7440
|
content = await (0, import_promises7.readFile)(fullSpecPath, "utf-8");
|
|
@@ -7224,7 +7516,7 @@ async function validateExecutableTraceability(root, config) {
|
|
|
7224
7516
|
if (entry.testId) {
|
|
7225
7517
|
let content;
|
|
7226
7518
|
try {
|
|
7227
|
-
content = await (0, import_promises7.readFile)((0,
|
|
7519
|
+
content = await (0, import_promises7.readFile)((0, import_node_path9.join)(root, normalizedRefFile), "utf-8");
|
|
7228
7520
|
} catch {
|
|
7229
7521
|
continue;
|
|
7230
7522
|
}
|
|
@@ -7401,11 +7693,11 @@ async function computeE2eCoverageStats(graph, root, thresholds = {}) {
|
|
|
7401
7693
|
let withExecutableRef = 0;
|
|
7402
7694
|
const statusBreakdown = {};
|
|
7403
7695
|
const chainTypeBreakdown = {};
|
|
7404
|
-
const e2eDir = (0,
|
|
7696
|
+
const e2eDir = (0, import_node_path9.join)(root, "artifacts", "tests", "e2e");
|
|
7405
7697
|
const tcFieldsMap = /* @__PURE__ */ new Map();
|
|
7406
7698
|
let e2eFiles;
|
|
7407
7699
|
try {
|
|
7408
|
-
e2eFiles = (await (0, import_promises7.readdir)(e2eDir)).filter((name) => /^test-.*\.md$/.test(name)).map((name) => (0,
|
|
7700
|
+
e2eFiles = (await (0, import_promises7.readdir)(e2eDir)).filter((name) => /^test-.*\.md$/.test(name)).map((name) => (0, import_node_path9.join)(e2eDir, name));
|
|
7409
7701
|
} catch {
|
|
7410
7702
|
e2eFiles = [];
|
|
7411
7703
|
}
|
|
@@ -7420,7 +7712,7 @@ async function computeE2eCoverageStats(graph, root, thresholds = {}) {
|
|
|
7420
7712
|
}
|
|
7421
7713
|
});
|
|
7422
7714
|
const parsed = (0, import_gray_matter.default)(raw);
|
|
7423
|
-
const batch = String(parsed.data.test_batch ?? (0,
|
|
7715
|
+
const batch = String(parsed.data.test_batch ?? (0, import_node_path9.basename)(filePath, (0, import_node_path9.extname)(filePath))).trim();
|
|
7424
7716
|
for (let i = 0; i < tcStarts.length; i++) {
|
|
7425
7717
|
const start = tcStarts[i];
|
|
7426
7718
|
const end = tcStarts[i + 1]?.index ?? lines.length;
|
|
@@ -7483,7 +7775,7 @@ async function computeE2eCoverageStats(graph, root, thresholds = {}) {
|
|
|
7483
7775
|
let hasActiveE2eRef = false;
|
|
7484
7776
|
for (const entry of parseExecutableRefLines(execRef)) {
|
|
7485
7777
|
const normalized = resolveExecutableRefFile(entry.file, allProjectFiles);
|
|
7486
|
-
if (!normalized || !(0,
|
|
7778
|
+
if (!normalized || !(0, import_node_fs5.existsSync)((0, import_node_path9.join)(root, normalized))) continue;
|
|
7487
7779
|
const accepting = await getAcceptingRunners(root, normalized, runners);
|
|
7488
7780
|
if (accepting.some((runner) => runner.kind === "e2e")) {
|
|
7489
7781
|
hasActiveE2eRef = true;
|
|
@@ -7542,7 +7834,7 @@ async function computeE2eCoverageStats(graph, root, thresholds = {}) {
|
|
|
7542
7834
|
const acCoverageRateByFeature = {};
|
|
7543
7835
|
const featureAcMap = /* @__PURE__ */ new Map();
|
|
7544
7836
|
for (const node of featureNodes) {
|
|
7545
|
-
const acs = parseAcceptanceCriteria(await (0, import_promises7.readFile)((0,
|
|
7837
|
+
const acs = parseAcceptanceCriteria(await (0, import_promises7.readFile)((0, import_node_path9.join)(root, node.path), "utf-8"));
|
|
7546
7838
|
featureAcMap.set(node.code, new Set(acs));
|
|
7547
7839
|
}
|
|
7548
7840
|
const coveredAcByFeature = /* @__PURE__ */ new Map();
|
|
@@ -7584,7 +7876,7 @@ async function computeE2eCoverageStats(graph, root, thresholds = {}) {
|
|
|
7584
7876
|
};
|
|
7585
7877
|
}
|
|
7586
7878
|
async function generateE2eRegistry(root, opts) {
|
|
7587
|
-
const e2eDir = (0,
|
|
7879
|
+
const e2eDir = (0, import_node_path9.join)(root, "artifacts", "tests", "e2e");
|
|
7588
7880
|
let files;
|
|
7589
7881
|
try {
|
|
7590
7882
|
files = (await (0, import_promises7.readdir)(e2eDir)).filter((name) => /^test-.*\.md$/.test(name)).sort();
|
|
@@ -7600,11 +7892,11 @@ async function generateE2eRegistry(root, opts) {
|
|
|
7600
7892
|
const batches = [];
|
|
7601
7893
|
let totalTestCases = 0;
|
|
7602
7894
|
for (const file of files) {
|
|
7603
|
-
const filePath = (0,
|
|
7895
|
+
const filePath = (0, import_node_path9.join)(e2eDir, file);
|
|
7604
7896
|
const raw = await (0, import_promises7.readFile)(filePath, "utf-8");
|
|
7605
7897
|
const parsed = (0, import_gray_matter.default)(raw);
|
|
7606
7898
|
const data = parsed.data;
|
|
7607
|
-
const batch = String(data.test_batch ?? (0,
|
|
7899
|
+
const batch = String(data.test_batch ?? (0, import_node_path9.basename)(file, (0, import_node_path9.extname)(file))).trim();
|
|
7608
7900
|
const relPath = `artifacts/tests/e2e/${file}`;
|
|
7609
7901
|
const scope = String(data.scope ?? "").trim();
|
|
7610
7902
|
const acCoverage = normalizeAcCoverageForRegistry(data.ac_coverage);
|
|
@@ -7728,7 +8020,7 @@ async function validatePartialRustEvidence(tcFields, tcKey, root, allFiles) {
|
|
|
7728
8020
|
if (!normalizedPath) {
|
|
7729
8021
|
return { hasValidPartialRust: false, detail: `partial_rust file not found: ${ref.file}` };
|
|
7730
8022
|
}
|
|
7731
|
-
const fullPath = (0,
|
|
8023
|
+
const fullPath = (0, import_node_path9.join)(root, normalizedPath);
|
|
7732
8024
|
let content;
|
|
7733
8025
|
try {
|
|
7734
8026
|
content = await (0, import_promises7.readFile)(fullPath, "utf-8");
|
|
@@ -7765,7 +8057,7 @@ function detectTestLevel(specFile, content) {
|
|
|
7765
8057
|
}
|
|
7766
8058
|
function resolveExecutableRefFile(refFile, allFiles) {
|
|
7767
8059
|
const normalized = refFile.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
7768
|
-
if (!normalized || (0,
|
|
8060
|
+
if (!normalized || (0, import_node_path9.isAbsolute)(refFile) || normalized.split("/").includes("..")) {
|
|
7769
8061
|
return void 0;
|
|
7770
8062
|
}
|
|
7771
8063
|
if (allFiles.includes(normalized)) {
|
|
@@ -7840,7 +8132,7 @@ function escapeRegExp(value) {
|
|
|
7840
8132
|
}
|
|
7841
8133
|
async function hasMarkdownTc(tcKey, e2eDir) {
|
|
7842
8134
|
const [batch, tcId] = tcKey.split(":");
|
|
7843
|
-
const filePath = (0,
|
|
8135
|
+
const filePath = (0, import_node_path9.join)(e2eDir, `${batch}.md`);
|
|
7844
8136
|
try {
|
|
7845
8137
|
const raw = await (0, import_promises7.readFile)(filePath, "utf-8");
|
|
7846
8138
|
const tcRegex = new RegExp(`^#{2,3}\\s+${escapeRegExp(tcId)}\\s*[:\uFF1A]?`, "m");
|
|
@@ -8073,7 +8365,7 @@ function normalizeDesignCode(value) {
|
|
|
8073
8365
|
if (!raw) {
|
|
8074
8366
|
return "";
|
|
8075
8367
|
}
|
|
8076
|
-
return (0,
|
|
8368
|
+
return (0, import_node_path9.basename)(raw, (0, import_node_path9.extname)(raw));
|
|
8077
8369
|
}
|
|
8078
8370
|
function toUid(type, code) {
|
|
8079
8371
|
return `${type}:${code}`;
|
|
@@ -8338,10 +8630,10 @@ function resolveArtifactContext(graph, opts) {
|
|
|
8338
8630
|
}
|
|
8339
8631
|
if (root) {
|
|
8340
8632
|
for (const ap of ALWAYS_PRESENT_ITEMS) {
|
|
8341
|
-
const fullPath = (0,
|
|
8633
|
+
const fullPath = (0, import_node_path9.join)(root, ap.path);
|
|
8342
8634
|
let stat;
|
|
8343
8635
|
try {
|
|
8344
|
-
stat = (0,
|
|
8636
|
+
stat = (0, import_node_fs5.statSync)(fullPath);
|
|
8345
8637
|
} catch {
|
|
8346
8638
|
stat = null;
|
|
8347
8639
|
}
|
|
@@ -8371,7 +8663,7 @@ function resolveArtifactContext(graph, opts) {
|
|
|
8371
8663
|
}
|
|
8372
8664
|
} else {
|
|
8373
8665
|
try {
|
|
8374
|
-
(0,
|
|
8666
|
+
(0, import_node_fs5.accessSync)(fullPath, import_node_fs5.constants.R_OK);
|
|
8375
8667
|
} catch {
|
|
8376
8668
|
const msg = `Required baseline artifact is not readable: ${ap.path}`;
|
|
8377
8669
|
if (!missing.includes(msg)) {
|
|
@@ -8568,15 +8860,14 @@ function formatContextMarkdown(manifest) {
|
|
|
8568
8860
|
}
|
|
8569
8861
|
return lines.join("\n");
|
|
8570
8862
|
}
|
|
8571
|
-
var
|
|
8863
|
+
var import_gray_matter, import_js_yaml, import_node_fs5, import_promises7, import_node_path9, TARGET_ARTIFACT_TYPES, NON_TARGET_ROLES, DEFAULT_SCHEMA, EMPTY_RELATION_FIELD_VALUES, VALID_TC_STATUSES, VALID_CHAIN_TYPES, DEPRECATED_CHAIN_TYPE_ALIASES, CONTEXT_CATEGORIES, TIER_ORDER;
|
|
8572
8864
|
var init_index = __esm({
|
|
8573
8865
|
"src/index.ts"() {
|
|
8574
|
-
import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
|
|
8575
8866
|
import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
8576
8867
|
import_js_yaml = __toESM(require("js-yaml"), 1);
|
|
8577
|
-
|
|
8868
|
+
import_node_fs5 = require("fs");
|
|
8578
8869
|
import_promises7 = require("fs/promises");
|
|
8579
|
-
|
|
8870
|
+
import_node_path9 = require("path");
|
|
8580
8871
|
init_packet_constants();
|
|
8581
8872
|
init_packet_validator();
|
|
8582
8873
|
init_glob_matcher();
|