intentdna 1.9.0 → 1.9.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.
Files changed (131) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +227 -87
  4. package/dist/cli/commands/run-lifecycle.d.ts +61 -11
  5. package/dist/cli/commands/run-lifecycle.js +184 -50
  6. package/dist/cli/commands/run-observer.d.ts +15 -0
  7. package/dist/cli/commands/run-observer.js +210 -0
  8. package/dist/cli/commands/run.d.ts +16 -20
  9. package/dist/cli/commands/run.js +461 -659
  10. package/dist/cli/commands/sync.js +16 -12
  11. package/dist/cli/index.js +14 -5
  12. package/dist/compiler/compile.d.ts +1 -0
  13. package/dist/compiler/compile.js +1 -1
  14. package/dist/compiler/controller.d.ts +16 -0
  15. package/dist/compiler/controller.js +693 -0
  16. package/dist/compiler/input-resolver.d.ts +2 -0
  17. package/dist/compiler/input-resolver.js +22 -6
  18. package/dist/hooks/cli.d.ts +45 -0
  19. package/dist/hooks/cli.js +263 -31
  20. package/dist/hooks/host-event.d.ts +57 -0
  21. package/dist/hooks/host-event.js +187 -0
  22. package/dist/hooks/index.d.ts +1 -0
  23. package/dist/hooks/index.js +1 -0
  24. package/dist/hooks/protocol.d.ts +7 -0
  25. package/dist/hooks/schema.d.ts +1 -0
  26. package/dist/hooks/schema.js +89 -1
  27. package/dist/hooks/state.d.ts +23 -1
  28. package/dist/hooks/state.js +9 -0
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.js +1 -0
  31. package/dist/mcp/index.js +2 -0
  32. package/dist/mcp/tools-run.d.ts +4 -0
  33. package/dist/mcp/tools-run.js +419 -0
  34. package/dist/mcp/tools-state.d.ts +1 -1
  35. package/dist/mcp/tools-state.js +13 -241
  36. package/dist/runtime/artifact-store.d.ts +146 -0
  37. package/dist/runtime/artifact-store.js +1436 -0
  38. package/dist/runtime/canonical-attempt-outcome.d.ts +12 -0
  39. package/dist/runtime/canonical-attempt-outcome.js +195 -0
  40. package/dist/runtime/canonical-json.d.ts +10 -0
  41. package/dist/runtime/canonical-json.js +105 -0
  42. package/dist/runtime/canonical-run-application.d.ts +93 -0
  43. package/dist/runtime/canonical-run-application.js +229 -0
  44. package/dist/runtime/canonical-run-service.d.ts +454 -0
  45. package/dist/runtime/canonical-run-service.js +4760 -0
  46. package/dist/runtime/canonical-runtime-composition.d.ts +22 -0
  47. package/dist/runtime/canonical-runtime-composition.js +34 -0
  48. package/dist/runtime/canonical-runtime-projection.d.ts +3 -0
  49. package/dist/runtime/canonical-runtime-projection.js +4 -0
  50. package/dist/runtime/canonical-target-compiler.d.ts +46 -0
  51. package/dist/runtime/canonical-target-compiler.js +514 -0
  52. package/dist/runtime/claude-agent-identity.d.ts +2 -0
  53. package/dist/runtime/claude-agent-identity.js +21 -0
  54. package/dist/runtime/executable-run-plan.d.ts +328 -0
  55. package/dist/runtime/executable-run-plan.js +1485 -0
  56. package/dist/runtime/execution-authority.d.ts +83 -0
  57. package/dist/runtime/execution-authority.js +98 -0
  58. package/dist/runtime/handoff-resolver.js +4 -1
  59. package/dist/runtime/harness-pull-adapter.d.ts +146 -0
  60. package/dist/runtime/harness-pull-adapter.js +315 -0
  61. package/dist/runtime/index.d.ts +39 -14
  62. package/dist/runtime/index.js +29 -7
  63. package/dist/runtime/local-execution-authority.d.ts +194 -0
  64. package/dist/runtime/local-execution-authority.js +2897 -0
  65. package/dist/runtime/local-execution-reconciliation.d.ts +20 -0
  66. package/dist/runtime/local-execution-reconciliation.js +107 -0
  67. package/dist/runtime/local-execution-supervisor-script.d.ts +7 -0
  68. package/dist/runtime/local-execution-supervisor-script.js +793 -0
  69. package/dist/runtime/local-provider-sandbox.d.ts +42 -0
  70. package/dist/runtime/local-provider-sandbox.js +154 -0
  71. package/dist/runtime/local-verifier-execution.d.ts +24 -0
  72. package/dist/runtime/local-verifier-execution.js +290 -0
  73. package/dist/runtime/local-windows-execution-supervisor-script.d.ts +6 -0
  74. package/dist/runtime/local-windows-execution-supervisor-script.js +788 -0
  75. package/dist/runtime/plan-store.d.ts +30 -0
  76. package/dist/runtime/plan-store.js +231 -0
  77. package/dist/runtime/process-tree.d.ts +9 -0
  78. package/dist/runtime/process-tree.js +97 -24
  79. package/dist/runtime/providers/codex.js +2 -2
  80. package/dist/runtime/push-driver.d.ts +184 -0
  81. package/dist/runtime/push-driver.js +1002 -0
  82. package/dist/runtime/result-store.d.ts +34 -3
  83. package/dist/runtime/result-store.js +1073 -2
  84. package/dist/runtime/run-binding.d.ts +68 -0
  85. package/dist/runtime/run-binding.js +278 -0
  86. package/dist/runtime/run-contracts.d.ts +575 -0
  87. package/dist/runtime/run-contracts.js +58 -7
  88. package/dist/runtime/run-controller.d.ts +1 -6
  89. package/dist/runtime/run-controller.js +0 -41
  90. package/dist/runtime/run-store.d.ts +85 -7
  91. package/dist/runtime/run-store.js +2528 -186
  92. package/dist/runtime/skill-adapter.d.ts +18 -7
  93. package/dist/runtime/skill-adapter.js +100 -742
  94. package/dist/runtime/structured-output-validator.d.ts +44 -0
  95. package/dist/runtime/structured-output-validator.js +171 -0
  96. package/dist/runtime/verifier-command-binding.d.ts +22 -0
  97. package/dist/runtime/verifier-command-binding.js +162 -0
  98. package/dist/runtime/verifier.d.ts +46 -6
  99. package/dist/runtime/verifier.js +355 -53
  100. package/dist/runtime/windows-job-keeper.d.ts +47 -0
  101. package/dist/runtime/windows-job-keeper.js +231 -0
  102. package/dist/runtime/worker-executor.d.ts +17 -1
  103. package/dist/runtime/worker-executor.js +26 -5
  104. package/dist/runtime/workflow-plan-adapter.d.ts +19 -0
  105. package/dist/runtime/workflow-plan-adapter.js +502 -6
  106. package/dist/runtime/workflow-runtime-manifest.d.ts +1 -0
  107. package/dist/runtime/workflow-runtime-manifest.js +5 -0
  108. package/dist/runtime/workspace-isolation.d.ts +29 -2
  109. package/dist/runtime/workspace-isolation.js +488 -11
  110. package/dist/runtime/workspace-observation.d.ts +44 -0
  111. package/dist/runtime/workspace-observation.js +216 -0
  112. package/dist/schema/controller-registry.d.ts +0 -7
  113. package/dist/schema/controller-registry.js +0 -8
  114. package/dist/schema/types.d.ts +84 -10
  115. package/dist/schema/types.js +2 -0
  116. package/dist/schema/validate.js +151 -1
  117. package/dist/schema/validators/controllers.d.ts +1 -1
  118. package/dist/schema/validators/controllers.js +126 -41
  119. package/dist/schema/workflow-authoring-contract.js +2 -0
  120. package/dist/schema/yaml-parser.js +1 -1
  121. package/dist/templates/flutter-rewrite-new.dna.yaml +1 -0
  122. package/dist/templates/flutter-rewrite.dna.yaml +87 -60
  123. package/dist/templates/safe-refactoring.dna.yaml +1 -0
  124. package/native/windows-job-keeper/README.md +80 -0
  125. package/native/windows-job-keeper/bin/aarch64/intentdna-windows-job-keeper.exe +0 -0
  126. package/native/windows-job-keeper/bin/x86_64/intentdna-windows-job-keeper.exe +0 -0
  127. package/native/windows-job-keeper/keeper.c +979 -0
  128. package/native/windows-job-keeper/manifest.json +33 -0
  129. package/package.json +6 -2
  130. package/scripts/build-windows-job-keeper.mjs +172 -0
  131. package/scripts/verify-windows-job-keeper.mjs +184 -0
@@ -0,0 +1,33 @@
1
+ {
2
+ "schema_version": "intentdna.windows_job_keeper_manifest.v1",
3
+ "protocol_version": "IDNA_WINDOWS_JOB_KEEPER_V1",
4
+ "source": {
5
+ "path": "keeper.c",
6
+ "sha256": "sha256:e93a634bbd5d6216aa35bd409350a3abd9cbf53aad4c314c368b7c3fec0d6f09"
7
+ },
8
+ "toolchain": {
9
+ "name": "zig",
10
+ "version": "0.16.0",
11
+ "build_script": {
12
+ "path": "../../scripts/build-windows-job-keeper.mjs",
13
+ "sha256": "sha256:973367e4d3c53c9ee725e27dc70fdfcb43ed4d3791968a8ce251691c15ac09e1"
14
+ },
15
+ "source_date_epoch": 0,
16
+ "targets": {
17
+ "x86_64": "x86_64-windows-gnu",
18
+ "aarch64": "aarch64-windows-gnu"
19
+ }
20
+ },
21
+ "binaries": {
22
+ "x86_64": {
23
+ "path": "bin/x86_64/intentdna-windows-job-keeper.exe",
24
+ "sha256": "sha256:23ca62d84e2787b9059b960f1ec1318d80c87a9f70bb84a81cc3587f5f8bcb1f",
25
+ "pe_machine": "0x8664"
26
+ },
27
+ "aarch64": {
28
+ "path": "bin/aarch64/intentdna-windows-job-keeper.exe",
29
+ "sha256": "sha256:9de5ccdcc75f3edaa02943ce9fbaffa735e44873921569f93e9071e5d9da7402",
30
+ "pe_machine": "0xaa64"
31
+ }
32
+ }
33
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intentdna",
3
- "version": "1.9.0",
3
+ "version": "1.9.3",
4
4
  "description": "Intent DNA — Declarative policy layer for AI agent behavior",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -11,9 +11,10 @@
11
11
  "dna-mcp": "dist/mcp/index.js"
12
12
  },
13
13
  "scripts": {
14
- "build": "tsc && mkdir -p dist/species dist/templates && cp src/species/*.json dist/species/ && cp src/templates/*.yaml dist/templates/ && node scripts/sync-plugin-version.cjs",
14
+ "build": "tsc && node scripts/copy-runtime-assets.mjs && node scripts/sync-plugin-version.cjs",
15
15
  "dev": "tsc --watch",
16
16
  "release:sync-plugin": "node scripts/sync-release-plugin.cjs",
17
+ "verify:windows-job-keeper": "node scripts/verify-windows-job-keeper.mjs",
17
18
  "test": "node --experimental-vm-modules node_modules/.bin/vitest run",
18
19
  "test:watch": "node --experimental-vm-modules node_modules/.bin/vitest"
19
20
  },
@@ -38,7 +39,10 @@
38
39
  "spec",
39
40
  ".claude-plugin",
40
41
  "hooks",
42
+ "native/windows-job-keeper",
43
+ "scripts/build-windows-job-keeper.mjs",
41
44
  "scripts/sync-release-plugin.cjs",
45
+ "scripts/verify-windows-job-keeper.mjs",
42
46
  "README.md",
43
47
  "LICENSE"
44
48
  ],
@@ -0,0 +1,172 @@
1
+ import { mkdir } from "node:fs/promises";
2
+ import { dirname, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { spawnSync } from "node:child_process";
5
+
6
+ const targets = Object.freeze({
7
+ x86_64: "x86_64-windows-gnu",
8
+ aarch64: "aarch64-windows-gnu",
9
+ });
10
+
11
+ const MAX_COUNT = 4096;
12
+ const MAX_GRACE_MS = 300_000;
13
+ const ZIG_VERSION = "0.16.0";
14
+
15
+ function hexUtf8(value) {
16
+ if (value.includes("\0")) throw new Error("keeper protocol values cannot contain NUL");
17
+ return Buffer.from(value, "utf8").toString("hex");
18
+ }
19
+
20
+ export function normalizeWindowsEnvironment(environment) {
21
+ const entries = Array.isArray(environment)
22
+ ? environment.map((entry) => {
23
+ const separator = entry.indexOf("=");
24
+ if (separator <= 0) throw new Error(`invalid environment entry: ${entry}`);
25
+ return [entry.slice(0, separator), entry.slice(separator + 1)];
26
+ })
27
+ : Object.entries(environment ?? {}).filter((entry) => entry[1] !== undefined);
28
+ if (entries.length > MAX_COUNT) throw new Error("too many environment entries");
29
+ const seen = new Set();
30
+ const normalized = entries.map(([key, value]) => {
31
+ if (!key || key.includes("=") || key.includes("\0")) {
32
+ throw new Error(`invalid environment key: ${key}`);
33
+ }
34
+ const stringValue = String(value);
35
+ if (stringValue.includes("\0")) throw new Error(`invalid environment value for ${key}`);
36
+ const folded = key.toLocaleLowerCase("en-US");
37
+ if (seen.has(folded)) throw new Error(`duplicate environment key: ${key}`);
38
+ seen.add(folded);
39
+ return `${key}=${stringValue}`;
40
+ });
41
+ normalized.sort((a, b) => a.localeCompare(b, "en-US", { sensitivity: "base" }));
42
+ const utf16Length = normalized.reduce((total, entry) => total + entry.length + 1, 1);
43
+ if (utf16Length > 32767) throw new Error("environment block exceeds 32767 UTF-16 units");
44
+ return normalized;
45
+ }
46
+
47
+ export function encodeWindowsKeeperConfig({
48
+ executable,
49
+ cwd = "",
50
+ stdinPath = "",
51
+ stdoutPath,
52
+ stderrPath,
53
+ maxOutputBytes = 16 * 1024 * 1024,
54
+ mode = "argv",
55
+ args = [],
56
+ commandLine,
57
+ environment,
58
+ naturalDrainGraceMs = 30_000,
59
+ forcedDrainGraceMs = 30_000,
60
+ }) {
61
+ if (!executable || !stdoutPath || !stderrPath) throw new Error("required keeper path missing");
62
+ if (!Number.isSafeInteger(maxOutputBytes) || maxOutputBytes <= 0) {
63
+ throw new Error("keeper output limit must be a positive safe integer");
64
+ }
65
+ if (!Number.isInteger(naturalDrainGraceMs) || naturalDrainGraceMs < 0 ||
66
+ naturalDrainGraceMs > MAX_GRACE_MS || !Number.isInteger(forcedDrainGraceMs) ||
67
+ forcedDrainGraceMs < 0 || forcedDrainGraceMs > MAX_GRACE_MS) {
68
+ throw new Error("keeper drain grace must be an integer from 0 through 300000");
69
+ }
70
+ const lines = [
71
+ "IDNA_WINDOWS_JOB_KEEPER_V1",
72
+ `exe:${hexUtf8(executable)}`,
73
+ `cwd:${hexUtf8(cwd)}`,
74
+ `stdin:${hexUtf8(stdinPath)}`,
75
+ `stdout:${hexUtf8(stdoutPath)}`,
76
+ `stderr:${hexUtf8(stderrPath)}`,
77
+ `max_output_bytes:${maxOutputBytes}`,
78
+ ];
79
+ if (mode === "argv") {
80
+ if (args.length > MAX_COUNT) throw new Error("too many command arguments");
81
+ lines.push("mode:argv", `argc:${args.length}`,
82
+ ...args.map((argument) => `arg:${hexUtf8(String(argument))}`));
83
+ } else if (mode === "verbatim") {
84
+ if (!commandLine || commandLine.length > 32766) {
85
+ throw new Error("verbatim command line must contain 1 through 32766 UTF-16 units");
86
+ }
87
+ lines.push("mode:verbatim", `command:${hexUtf8(commandLine)}`);
88
+ } else {
89
+ throw new Error(`unsupported command mode: ${mode}`);
90
+ }
91
+ const normalizedEnvironment = normalizeWindowsEnvironment(environment);
92
+ lines.push(`envc:${normalizedEnvironment.length}`,
93
+ ...normalizedEnvironment.map((entry) => `env:${hexUtf8(entry)}`),
94
+ `natural_drain_grace_ms:${naturalDrainGraceMs}`,
95
+ `forced_drain_grace_ms:${forcedDrainGraceMs}`,
96
+ "end");
97
+ return `${lines.join("\n")}\n`;
98
+ }
99
+
100
+ export function quoteWindowsCrtArgument(value) {
101
+ if (value.length > 0 && !/[\s"]/.test(value)) return value;
102
+ let output = '"';
103
+ let backslashes = 0;
104
+ for (const character of value) {
105
+ if (character === "\\") {
106
+ backslashes += 1;
107
+ continue;
108
+ }
109
+ if (character === '"') output += "\\".repeat(backslashes * 2 + 1);
110
+ else output += "\\".repeat(backslashes);
111
+ backslashes = 0;
112
+ output += character;
113
+ }
114
+ return `${output}${"\\".repeat(backslashes * 2)}"`;
115
+ }
116
+
117
+ export function buildCommand({
118
+ arch = process.env.IDNA_WINDOWS_KEEPER_ARCH ?? "x86_64",
119
+ zig = process.env.ZIG ?? "zig",
120
+ output,
121
+ } = {}) {
122
+ const target = targets[arch];
123
+ if (!target) throw new Error(`unsupported architecture: ${arch}`);
124
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
125
+ const source = resolve(root, "native/windows-job-keeper/keeper.c");
126
+ const destination = resolve(output ?? process.env.IDNA_WINDOWS_KEEPER_OUT ??
127
+ `build/windows-job-keeper/${arch}/intentdna-windows-job-keeper.exe`);
128
+ return {
129
+ command: zig,
130
+ destination,
131
+ args: [
132
+ "cc", "-target", target, "-std=c11", "-Os", "-fno-ident",
133
+ "-municode", source, "-lbcrypt",
134
+ "-Wl,--strip-all", "-o", destination,
135
+ ],
136
+ };
137
+ }
138
+
139
+ export function assertZigVersion(version) {
140
+ if (version !== ZIG_VERSION) {
141
+ throw new Error(`Windows Job keeper requires Zig ${ZIG_VERSION}, received ${version}`);
142
+ }
143
+ }
144
+
145
+ export function verifyZigVersion(zig) {
146
+ const result = spawnSync(zig, ["version"], { encoding: "utf8" });
147
+ if (result.error) throw result.error;
148
+ if (result.status !== 0) {
149
+ throw new Error(`unable to read Zig version from ${zig}: ${result.stderr.trim()}`);
150
+ }
151
+ assertZigVersion(result.stdout.trim());
152
+ }
153
+
154
+ async function main() {
155
+ const plan = buildCommand();
156
+ if (process.argv.includes("--print")) {
157
+ process.stdout.write(`${JSON.stringify(plan)}\n`);
158
+ return;
159
+ }
160
+ verifyZigVersion(plan.command);
161
+ await mkdir(dirname(plan.destination), { recursive: true });
162
+ const result = spawnSync(plan.command, plan.args, { stdio: "inherit", env: {
163
+ ...process.env,
164
+ SOURCE_DATE_EPOCH: "0",
165
+ } });
166
+ if (result.error) throw result.error;
167
+ if (result.status !== 0) process.exitCode = result.status ?? 1;
168
+ }
169
+
170
+ const invoked = process.argv[1] &&
171
+ resolve(process.argv[1]) === fileURLToPath(import.meta.url);
172
+ if (invoked) await main();
@@ -0,0 +1,184 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { createHash } from "node:crypto";
3
+ import { existsSync } from "node:fs";
4
+ import { readFile } from "node:fs/promises";
5
+ import { dirname, join, posix, resolve, win32 } from "node:path";
6
+ import { fileURLToPath, pathToFileURL } from "node:url";
7
+
8
+ const ARCHITECTURES = Object.freeze({
9
+ x86_64: Object.freeze({
10
+ nodeArchitecture: "x64",
11
+ peMachine: "0x8664",
12
+ target: "x86_64-windows-gnu",
13
+ }),
14
+ aarch64: Object.freeze({
15
+ nodeArchitecture: "arm64",
16
+ peMachine: "0xaa64",
17
+ target: "aarch64-windows-gnu",
18
+ }),
19
+ });
20
+
21
+ const MANIFEST_PACKAGE_DIRECTORY = "native/windows-job-keeper";
22
+ const TOOLCHAIN = Object.freeze({
23
+ name: "zig",
24
+ version: "0.16.0",
25
+ buildScriptPath: "../../scripts/build-windows-job-keeper.mjs",
26
+ sourceDateEpoch: 0,
27
+ });
28
+
29
+ export function sha256(bytes) {
30
+ return `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
31
+ }
32
+
33
+ export function readPeMachine(bytes) {
34
+ if (!Buffer.isBuffer(bytes) || bytes.length < 64 || bytes[0] !== 0x4d || bytes[1] !== 0x5a) {
35
+ throw new Error("binary is not a valid PE image: missing MZ header");
36
+ }
37
+ const peOffset = bytes.readUInt32LE(0x3c);
38
+ if (peOffset > bytes.length - 6 || bytes.toString("binary", peOffset, peOffset + 4) !== "PE\u0000\u0000") {
39
+ throw new Error("binary is not a valid PE image: missing PE header");
40
+ }
41
+ return `0x${bytes.readUInt16LE(peOffset + 4).toString(16).padStart(4, "0")}`;
42
+ }
43
+
44
+ function verifyToolchain(manifest) {
45
+ const toolchain = manifest.toolchain;
46
+ if (toolchain.name !== TOOLCHAIN.name || toolchain.version !== TOOLCHAIN.version ||
47
+ toolchain.source_date_epoch !== TOOLCHAIN.sourceDateEpoch ||
48
+ toolchain.build_script.path !== TOOLCHAIN.buildScriptPath) {
49
+ throw new Error("Windows Job keeper toolchain identity mismatch");
50
+ }
51
+ for (const [architecture, expected] of Object.entries(ARCHITECTURES)) {
52
+ if (toolchain.targets[architecture] !== expected.target) {
53
+ throw new Error(`Windows Job keeper target mismatch for ${architecture}`);
54
+ }
55
+ }
56
+ }
57
+
58
+ export async function verifyReleaseArtifacts(manifest, manifestPath) {
59
+ verifyToolchain(manifest);
60
+ const manifestRoot = dirname(resolve(manifestPath));
61
+ const sourcePath = resolve(manifestRoot, manifest.source.path);
62
+ if (sha256(await readFile(sourcePath)) !== manifest.source.sha256) {
63
+ throw new Error(`source SHA-256 mismatch: ${sourcePath}`);
64
+ }
65
+ const buildScriptPath = resolve(manifestRoot, manifest.toolchain.build_script.path);
66
+ if (sha256(await readFile(buildScriptPath)) !== manifest.toolchain.build_script.sha256) {
67
+ throw new Error(`build script SHA-256 mismatch: ${buildScriptPath}`);
68
+ }
69
+ for (const [architecture, expected] of Object.entries(ARCHITECTURES)) {
70
+ const binary = manifest.binaries[architecture];
71
+ const path = resolve(manifestRoot, binary.path);
72
+ const bytes = await readFile(path);
73
+ if (sha256(bytes) !== binary.sha256) throw new Error(`binary SHA-256 mismatch: ${path}`);
74
+ const machine = readPeMachine(bytes);
75
+ if (machine !== expected.peMachine || machine !== binary.pe_machine) {
76
+ throw new Error(`PE machine mismatch for ${path}: expected ${expected.peMachine}, received ${machine}`);
77
+ }
78
+ }
79
+ }
80
+
81
+ export function requiredNpmPackageFiles(manifest) {
82
+ return [
83
+ "native/windows-job-keeper/manifest.json",
84
+ manifestMemberPackagePath(manifest.source.path),
85
+ ...Object.keys(ARCHITECTURES).map((architecture) =>
86
+ manifestMemberPackagePath(manifest.binaries[architecture].path)),
87
+ manifestMemberPackagePath(manifest.toolchain.build_script.path),
88
+ "scripts/verify-windows-job-keeper.mjs",
89
+ ];
90
+ }
91
+
92
+ function manifestMemberPackagePath(member) {
93
+ const path = posix.normalize(posix.join(MANIFEST_PACKAGE_DIRECTORY, member));
94
+ if (path === ".." || path.startsWith("../") || posix.isAbsolute(path)) {
95
+ throw new Error(`manifest member escapes the npm package: ${member}`);
96
+ }
97
+ return path;
98
+ }
99
+
100
+ export function verifyNpmPackageFileList(manifest, files) {
101
+ const included = new Set(files);
102
+ const missing = requiredNpmPackageFiles(manifest).filter((path) => !included.has(path));
103
+ if (missing.length > 0) throw new Error(`npm package is missing Windows Job keeper files: ${missing.join(", ")}`);
104
+ }
105
+
106
+ export function npmCliInvocation({
107
+ environment = process.env,
108
+ platform = process.platform,
109
+ nodeExecutable = process.execPath,
110
+ pathExists = existsSync,
111
+ } = {}) {
112
+ const npmExecPath = environment.npm_execpath?.trim();
113
+ if (npmExecPath) {
114
+ return {
115
+ command: environment.npm_node_execpath?.trim() || nodeExecutable,
116
+ args: [npmExecPath],
117
+ };
118
+ }
119
+ if (platform !== "win32") return { command: "npm", args: [] };
120
+
121
+ const nodeDirectory = win32.dirname(nodeExecutable);
122
+ const candidates = [
123
+ win32.join(nodeDirectory, "node_modules", "npm", "bin", "npm-cli.js"),
124
+ win32.join(nodeDirectory, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
125
+ ...(environment.npm_config_prefix?.trim()
126
+ ? [win32.join(environment.npm_config_prefix.trim(), "node_modules", "npm", "bin", "npm-cli.js")]
127
+ : []),
128
+ ...(environment.APPDATA?.trim()
129
+ ? [win32.join(environment.APPDATA.trim(), "npm", "node_modules", "npm", "bin", "npm-cli.js")]
130
+ : []),
131
+ ];
132
+ const npmCliPath = candidates.find((candidate) => pathExists(candidate));
133
+ if (!npmCliPath) {
134
+ throw new Error(`unable to resolve npm CLI for Node executable: ${nodeExecutable}`);
135
+ }
136
+ return {
137
+ command: nodeExecutable,
138
+ args: [npmCliPath],
139
+ };
140
+ }
141
+
142
+ export function npmPackFileList(root = repositoryRoot()) {
143
+ const invocation = npmCliInvocation();
144
+ const output = execFileSync(invocation.command, [
145
+ ...invocation.args,
146
+ "pack",
147
+ "--dry-run",
148
+ "--ignore-scripts",
149
+ "--json",
150
+ ], {
151
+ cwd: root,
152
+ encoding: "utf8",
153
+ });
154
+ const result = JSON.parse(output);
155
+ if (!Array.isArray(result) || result.length !== 1 || !Array.isArray(result[0]?.files)) {
156
+ throw new Error("npm pack returned an unexpected file list");
157
+ }
158
+ return result[0].files.map(({ path }) => path);
159
+ }
160
+
161
+ export function repositoryRoot() {
162
+ return resolve(dirname(fileURLToPath(import.meta.url)), "..");
163
+ }
164
+
165
+ async function main() {
166
+ const root = repositoryRoot();
167
+ const manifestPath = resolve(root, "native/windows-job-keeper/manifest.json");
168
+ const {
169
+ parseWindowsJobKeeperManifest,
170
+ resolveWindowsJobKeeperArtifact,
171
+ } = await import(
172
+ pathToFileURL(resolve(root, "dist/runtime/windows-job-keeper.js")).href
173
+ );
174
+ const manifest = parseWindowsJobKeeperManifest(JSON.parse(await readFile(manifestPath, "utf8")));
175
+ await verifyReleaseArtifacts(manifest, manifestPath);
176
+ for (const expected of Object.values(ARCHITECTURES)) {
177
+ resolveWindowsJobKeeperArtifact({ platform: "win32", architecture: expected.nodeArchitecture });
178
+ }
179
+ verifyNpmPackageFileList(manifest, npmPackFileList(root));
180
+ process.stdout.write("Windows Job keeper artifacts and npm package contents verified.\n");
181
+ }
182
+
183
+ const invoked = process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url);
184
+ if (invoked) await main();