svharness 0.8.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.
Files changed (134) hide show
  1. package/README.md +531 -0
  2. package/bin/cli.js +3 -0
  3. package/dist/adapters/_frontmatter.js +24 -0
  4. package/dist/adapters/claude-code.js +12 -0
  5. package/dist/adapters/codechat.js +12 -0
  6. package/dist/adapters/cursor.js +19 -0
  7. package/dist/adapters/generic.js +19 -0
  8. package/dist/adapters/index.js +26 -0
  9. package/dist/adapters/qoder.js +12 -0
  10. package/dist/commands/apply.js +272 -0
  11. package/dist/commands/init.js +420 -0
  12. package/dist/core/agent-injector.js +192 -0
  13. package/dist/core/next-steps.js +91 -0
  14. package/dist/core/render-meta.js +81 -0
  15. package/dist/core/repomix-pack.js +54 -0
  16. package/dist/core/scaffold.js +93 -0
  17. package/dist/core/state.js +80 -0
  18. package/dist/index.js +239 -0
  19. package/dist/types.js +5 -0
  20. package/dist/utils/baseline-copy.js +591 -0
  21. package/dist/utils/baseline-defaults.js +106 -0
  22. package/dist/utils/logger.js +56 -0
  23. package/dist/utils/validate-args.js +132 -0
  24. package/dist/utils/version.js +23 -0
  25. package/dist/wiki/abort.js +30 -0
  26. package/dist/wiki/config.js +79 -0
  27. package/dist/wiki/defaults.js +16 -0
  28. package/dist/wiki/envLoader.js +78 -0
  29. package/dist/wiki/index.js +29 -0
  30. package/dist/wiki/openaiCompat.js +219 -0
  31. package/dist/wiki/repowikiCanonicalSections.js +67 -0
  32. package/dist/wiki/repowikiCheckpoint.js +106 -0
  33. package/dist/wiki/repowikiConfig.js +9 -0
  34. package/dist/wiki/repowikiGit.js +73 -0
  35. package/dist/wiki/repowikiIndexer.js +824 -0
  36. package/dist/wiki/repowikiMarkdownPost.js +123 -0
  37. package/dist/wiki/repowikiMetadataContent.js +64 -0
  38. package/dist/wiki/repowikiMetadataJson.js +15 -0
  39. package/dist/wiki/repowikiScanner.js +156 -0
  40. package/dist/wiki/repowikiStructureNav.js +286 -0
  41. package/dist/wiki/repowikiStructureNormalize.js +218 -0
  42. package/dist/wiki/wikiStructureXml.js +316 -0
  43. package/dist/wiki/wikiTasksWriter.js +127 -0
  44. package/package.json +57 -0
  45. package/templates/_shared/apply-skills/harness-apply-skills-main.md +91 -0
  46. package/templates/_shared/build-rules/harness-build-rule-agent-agnostic.md +35 -0
  47. package/templates/_shared/build-rules/harness-build-rule-chinese-only.md +49 -0
  48. package/templates/_shared/build-rules/harness-build-rule-memory-write.md +31 -0
  49. package/templates/_shared/build-rules/harness-build-rule-orchestrator-flow.md +25 -0
  50. package/templates/_shared/build-rules/harness-build-rule-skills-tasks-output.md +35 -0
  51. package/templates/_shared/build-rules/harness-build-rule-specs-schema.md +32 -0
  52. package/templates/_shared/build-rules/harness-build-rule-user-interaction.md +63 -0
  53. package/templates/_shared/build-skills/harness-build-skill-knowledge-builder.md +120 -0
  54. package/templates/_shared/build-skills/harness-build-skill-orchestrator.md +87 -0
  55. package/templates/_shared/build-skills/harness-build-skill-spec-builder.md +85 -0
  56. package/templates/_shared/build-skills/harness-build-skill-wiki-writer.md +77 -0
  57. package/templates/_shared/meta/AGENTS.md.ejs +53 -0
  58. package/templates/_shared/meta/CHANGELOG.md.ejs +15 -0
  59. package/templates/_shared/meta/README.md.ejs +51 -0
  60. package/templates/_shared/meta/VERSION.ejs +1 -0
  61. package/templates/_shared/meta/harness.yaml.ejs +52 -0
  62. package/templates/_shared/skeleton/agent-env/memory/categories/.gitkeep +1 -0
  63. package/templates/_shared/skeleton/agent-env/memory/inbox/.gitkeep +1 -0
  64. package/templates/_shared/skeleton/agent-env/skills/.gitkeep +1 -0
  65. package/templates/_shared/skeleton/agent-env/tools/.gitkeep +1 -0
  66. package/templates/_shared/skeleton/assets/baseline/code/.gitkeep +1 -0
  67. package/templates/_shared/skeleton/assets/baseline/repomix/.gitkeep +1 -0
  68. package/templates/_shared/skeleton/assets/baseline/wiki/.gitkeep +1 -0
  69. package/templates/_shared/skeleton/assets/raw/.gitkeep +1 -0
  70. package/templates/_shared/skeleton/assets/requirements/.gitkeep +1 -0
  71. package/templates/_shared/skeleton/commands/install/.gitkeep +1 -0
  72. package/templates/_shared/skeleton/commands/update/.gitkeep +1 -0
  73. package/templates/_shared/skeleton/specs/behavior/schema.json +39 -0
  74. package/templates/_shared/skeleton/specs/interfaces/schema.json +38 -0
  75. package/templates/_shared/skeleton/specs/signals/schema.json +37 -0
  76. package/templates/_shared/skeleton/specs/ui/schema.json +44 -0
  77. package/templates/_shared/skeleton/tasks/templates/.gitkeep +0 -0
  78. package/templates/android-compose/skeleton/agent-env/rules/harness-compose-mandatory.mdc +49 -0
  79. package/templates/android-compose/skeleton/agent-env/rules/harness-coroutines-scope.mdc +52 -0
  80. package/templates/android-compose/skeleton/agent-env/rules/harness-hilt-injection.mdc +47 -0
  81. package/templates/android-compose/skeleton/agent-env/rules/harness-mvi-layering.mdc +58 -0
  82. package/templates/android-compose/skeleton/agent-env/skills/harness-android-architecture/SKILL.md +260 -0
  83. package/templates/android-compose/skeleton/agent-env/skills/harness-android-architecture/references/gradle-module-patterns.md +66 -0
  84. package/templates/android-compose/skeleton/agent-env/skills/harness-android-architecture/references/implementation-checklist.md +45 -0
  85. package/templates/android-compose/skeleton/agent-env/skills/harness-android-architecture/references/udf-data-flow.md +80 -0
  86. package/templates/android-compose/skeleton/agent-env/skills/harness-android-cli/SKILL.md +79 -0
  87. package/templates/android-compose/skeleton/agent-env/skills/harness-android-cli/references/interact.md +83 -0
  88. package/templates/android-compose/skeleton/agent-env/skills/harness-android-cli/references/journeys.md +97 -0
  89. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-audit/SKILL.md +162 -0
  90. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-audit/references/canonical-sources.md +116 -0
  91. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-audit/references/diagnostics.md +182 -0
  92. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-audit/references/report-template.md +135 -0
  93. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-audit/references/scoring.md +277 -0
  94. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-audit/references/search-playbook.md +303 -0
  95. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-audit/scripts/compose-reports.init.gradle +58 -0
  96. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-state/SKILL.md +196 -0
  97. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-ui/SKILL.md +192 -0
  98. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-ui/references/composable-api-guide.md +123 -0
  99. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-ui/references/performance-recipes.md +97 -0
  100. package/templates/android-compose/skeleton/agent-env/skills/harness-compose-ui/references/state-patterns.md +93 -0
  101. package/templates/android-compose/skeleton/agent-env/skills/harness-kotlin-coroutines/SKILL.md +167 -0
  102. package/templates/android-compose/skeleton/agent-env/skills/harness-r8-analyzer/SKILL.md +45 -0
  103. package/templates/android-compose/skeleton/agent-env/skills/harness-r8-analyzer/references/CONFIGURATION.md +44 -0
  104. package/templates/android-compose/skeleton/agent-env/skills/harness-r8-analyzer/references/KEEP-RULES-IMPACT-HIERARCHY.md +83 -0
  105. package/templates/android-compose/skeleton/agent-env/skills/harness-r8-analyzer/references/REDUNDANT-RULES.md +222 -0
  106. package/templates/android-compose/skeleton/agent-env/skills/harness-r8-analyzer/references/REFLECTION-GUIDE.md +139 -0
  107. package/templates/android-compose/skeleton/agent-env/skills/harness-r8-analyzer/references/android/topic/performance/app-optimization/enable-app-optimization.md +176 -0
  108. package/templates/android-compose/skeleton/agent-env/skills/harness-r8-analyzer/references/android/training/testing/other-components/ui-automator.md +312 -0
  109. package/templates/android-compose/skeleton/agent-env/skills/harness-xml-to-compose/SKILL.md +87 -0
  110. package/templates/android-compose/skeleton/agent-env/skills/harness-xml-to-compose/references/analysis-of-the-project-and-layout.md +42 -0
  111. package/templates/android-compose/skeleton/agent-env/skills/harness-xml-to-compose/references/android/develop/ui/compose/designsystems/migrate-xml-theme-to-compose.md +168 -0
  112. package/templates/android-compose/skeleton/agent-env/skills/harness-xml-to-compose/references/android/develop/ui/compose/setup-compose-dependencies-and-compiler.md +183 -0
  113. package/templates/android-compose/skeleton/agent-env/skills/harness-xml-to-compose/references/identify-optimal-xml-candidate.md +31 -0
  114. package/templates/android-compose/skeleton/agent-env/skills/harness-xml-to-compose/references/xml-layout-migration.md +86 -0
  115. package/templates/android-xml/skeleton/agent-env/rules/seed-aidl-thread.md +29 -0
  116. package/templates/android-xml/skeleton/agent-env/rules/seed-lifecycle-awareness.md +32 -0
  117. package/templates/android-xml/skeleton/agent-env/rules/seed-mvc-layering.md +32 -0
  118. package/templates/android-xml/skeleton/agent-env/rules/seed-view-binding.md +33 -0
  119. package/templates/android-xml/skeleton/agent-env/rules/seed-xml-styling.md +27 -0
  120. package/templates/cpp/skeleton/agent-env/rules/seed-cmake-explicit-sources.md +31 -0
  121. package/templates/cpp/skeleton/agent-env/rules/seed-header-guards.md +34 -0
  122. package/templates/cpp/skeleton/agent-env/rules/seed-include-layering.md +39 -0
  123. package/templates/cpp/skeleton/agent-env/rules/seed-no-cyclic-deps.md +29 -0
  124. package/templates/cpp/skeleton/agent-env/rules/seed-raii.md +30 -0
  125. package/templates/python/skeleton/agent-env/rules/seed-context-managers.md +60 -0
  126. package/templates/python/skeleton/agent-env/rules/seed-docstrings.md +48 -0
  127. package/templates/python/skeleton/agent-env/rules/seed-import-order.md +49 -0
  128. package/templates/python/skeleton/agent-env/rules/seed-pep8-naming.md +45 -0
  129. package/templates/python/skeleton/agent-env/rules/seed-type-annotations.md +43 -0
  130. package/templates/web-react/skeleton/agent-env/rules/seed-controlled-component.md +43 -0
  131. package/templates/web-react/skeleton/agent-env/rules/seed-effect-cleanup.md +43 -0
  132. package/templates/web-react/skeleton/agent-env/rules/seed-hook-rules.md +42 -0
  133. package/templates/web-react/skeleton/agent-env/rules/seed-key-stability.md +39 -0
  134. package/templates/web-react/skeleton/agent-env/rules/seed-no-props-drilling.md +43 -0
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultWikiFolderSegment = defaultWikiFolderSegment;
4
+ exports.buildUniqueSectionFolderSegments = buildUniqueSectionFolderSegments;
5
+ exports.sectionFolderSegmentForPage = sectionFolderSegmentForPage;
6
+ exports.formatSectionFolderMapSummary = formatSectionFolderMapSummary;
7
+ const wikiStructureXml_1 = require("./wikiStructureXml");
8
+ /**
9
+ * When `structure.xml` has no `<sections>`, all pages live under one folder derived from the
10
+ * wiki outline `<title>`, with a language fallback if the title slug is empty.
11
+ */
12
+ function defaultWikiFolderSegment(wikiOutlineTitle, langFolder) {
13
+ const s = (0, wikiStructureXml_1.slugifyWikiTitle)(wikiOutlineTitle);
14
+ if (s)
15
+ return s;
16
+ return langFolder === "zh" ? "文档" : "wiki";
17
+ }
18
+ /**
19
+ * Map each section id to a unique subdirectory name under the language folder
20
+ * (slug of `<section>` `<title>`, with numeric suffixes if titles collide).
21
+ */
22
+ function buildUniqueSectionFolderSegments(groups) {
23
+ const used = new Set();
24
+ const idToFolder = new Map();
25
+ for (const g of groups) {
26
+ let base = (0, wikiStructureXml_1.slugifyWikiTitle)(g.title) || (0, wikiStructureXml_1.slugifyWikiTitle)(g.id) || "section";
27
+ let candidate = base;
28
+ let n = 2;
29
+ while (used.has(candidate)) {
30
+ candidate = `${base}-${n}`;
31
+ n++;
32
+ }
33
+ used.add(candidate);
34
+ idToFolder.set(g.id, candidate);
35
+ }
36
+ return idToFolder;
37
+ }
38
+ /**
39
+ * Resolve the first path segment under `<lang>/…` for a page using `<sections>` when present.
40
+ */
41
+ function sectionFolderSegmentForPage(page, sectionGroups, outlineFolderSegment, folderBySectionId) {
42
+ if (sectionGroups.length === 0) {
43
+ return outlineFolderSegment;
44
+ }
45
+ const ps = page.parentSection?.trim();
46
+ if (ps && folderBySectionId.has(ps)) {
47
+ return folderBySectionId.get(ps);
48
+ }
49
+ const containing = sectionGroups.find((s) => s.pageIds.includes(page.id));
50
+ if (containing) {
51
+ return folderBySectionId.get(containing.id) ?? outlineFolderSegment;
52
+ }
53
+ return outlineFolderSegment;
54
+ }
55
+ function formatSectionFolderMapSummary(folderByPageId, pageOrder) {
56
+ const byFolder = new Map();
57
+ for (const id of pageOrder) {
58
+ const f = folderByPageId.get(id) ?? "";
59
+ const arr = byFolder.get(f) ?? [];
60
+ arr.push(id);
61
+ byFolder.set(f, arr);
62
+ }
63
+ return [...byFolder.entries()]
64
+ .sort((a, b) => a[0].localeCompare(b[0]))
65
+ .map(([folder, ids]) => `${folder}: ${ids.join(",")}`)
66
+ .join(" | ");
67
+ }
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.REPOWIKI_CHECKPOINT_FILENAME = void 0;
37
+ exports.checkpointPath = checkpointPath;
38
+ exports.readRepowikiCheckpoint = readRepowikiCheckpoint;
39
+ exports.checkpointMatchesRun = checkpointMatchesRun;
40
+ exports.writeRepowikiCheckpoint = writeRepowikiCheckpoint;
41
+ exports.clearRepowikiCheckpoint = clearRepowikiCheckpoint;
42
+ const fs = __importStar(require("fs/promises"));
43
+ const path = __importStar(require("path"));
44
+ exports.REPOWIKI_CHECKPOINT_FILENAME = "checkpoint.json";
45
+ function normFs(p) {
46
+ return path.normalize(p).replace(/\\/g, "/");
47
+ }
48
+ function checkpointPath(wikiBaseFs) {
49
+ return path.join(wikiBaseFs, exports.REPOWIKI_CHECKPOINT_FILENAME);
50
+ }
51
+ async function readRepowikiCheckpoint(wikiBaseFs) {
52
+ try {
53
+ const raw = await fs.readFile(checkpointPath(wikiBaseFs), "utf8");
54
+ const j = JSON.parse(raw);
55
+ if (j.version !== 1 || typeof j.runId !== "string" || typeof j.sourceRootFs !== "string") {
56
+ return null;
57
+ }
58
+ if (typeof j.wikiBaseFs !== "string" || typeof j.targetLang !== "string") {
59
+ return null;
60
+ }
61
+ return {
62
+ version: 1,
63
+ runId: j.runId,
64
+ status: j.status === "done" ? "done" : "running",
65
+ sourceRootFs: j.sourceRootFs,
66
+ wikiBaseFs: j.wikiBaseFs,
67
+ indexedCommit: j.indexedCommit ?? null,
68
+ targetLang: j.targetLang,
69
+ languages: Array.isArray(j.languages) ? j.languages : undefined,
70
+ completed: Array.isArray(j.completed) ? [...j.completed] : [],
71
+ fileByPageId: j.fileByPageId && typeof j.fileByPageId === "object"
72
+ ? { ...j.fileByPageId }
73
+ : {},
74
+ };
75
+ }
76
+ catch {
77
+ return null;
78
+ }
79
+ }
80
+ function checkpointMatchesRun(cp, sourceRootFs, wikiBaseFs, targetLangFolder) {
81
+ return (normFs(cp.sourceRootFs) === normFs(sourceRootFs) &&
82
+ normFs(cp.wikiBaseFs) === normFs(wikiBaseFs) &&
83
+ cp.targetLang === targetLangFolder &&
84
+ cp.status !== "done");
85
+ }
86
+ /** Atomic replace via temp + rename. */
87
+ async function writeRepowikiCheckpoint(wikiBaseFs, data) {
88
+ await fs.mkdir(wikiBaseFs, { recursive: true });
89
+ const finalPath = checkpointPath(wikiBaseFs);
90
+ const tmp = path.join(wikiBaseFs, `.checkpoint-${data.runId}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}.tmp.json`);
91
+ const payload = {
92
+ ...data,
93
+ wikiBaseFs: normFs(data.wikiBaseFs),
94
+ sourceRootFs: normFs(data.sourceRootFs),
95
+ };
96
+ await fs.writeFile(tmp, JSON.stringify(payload, null, 2), "utf8");
97
+ await fs.rename(tmp, finalPath);
98
+ }
99
+ async function clearRepowikiCheckpoint(wikiBaseFs) {
100
+ try {
101
+ await fs.unlink(checkpointPath(wikiBaseFs));
102
+ }
103
+ catch {
104
+ /* missing is fine */
105
+ }
106
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadRepowikiMetadata = void 0;
4
+ /**
5
+ * Compatibility shim — keeps the original filename used by ported modules
6
+ * (e.g. `repowikiStructureNav.ts`) so we avoid churning their imports.
7
+ */
8
+ var config_1 = require("./config");
9
+ Object.defineProperty(exports, "loadRepowikiMetadata", { enumerable: true, get: function () { return config_1.loadRepowikiMetadata; } });
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.gitHeadAt = gitHeadAt;
37
+ exports.basenameSafe = basenameSafe;
38
+ exports.gitChangedPathCountSince = gitChangedPathCountSince;
39
+ const child_process_1 = require("child_process");
40
+ const path = __importStar(require("path"));
41
+ async function gitHeadAt(cwdFs) {
42
+ return new Promise((resolve) => {
43
+ const gitBin = process.platform === "win32" ? "git.exe" : "git";
44
+ (0, child_process_1.execFile)(gitBin, ["-C", cwdFs, "rev-parse", "HEAD"], { timeout: 8000 }, (err, stdout) => {
45
+ if (err) {
46
+ resolve(undefined);
47
+ return;
48
+ }
49
+ const h = stdout.trim();
50
+ resolve(h.length > 7 ? h : undefined);
51
+ });
52
+ });
53
+ }
54
+ function basenameSafe(p) {
55
+ return path.basename(p.replace(/[/\\]+$/, "")) || "workspace";
56
+ }
57
+ /** Count paths changed between `fromRef` and current `HEAD` (merge-base range). Undefined if git fails. */
58
+ async function gitChangedPathCountSince(cwdFs, fromCommit) {
59
+ const from = fromCommit.trim();
60
+ if (from.length < 7)
61
+ return undefined;
62
+ return new Promise((resolve) => {
63
+ const gitBin = process.platform === "win32" ? "git.exe" : "git";
64
+ (0, child_process_1.execFile)(gitBin, ["-C", cwdFs, "diff", "--name-only", `${from}...HEAD`], { timeout: 12_000, maxBuffer: 4 * 1024 * 1024 }, (err, stdout) => {
65
+ if (err) {
66
+ resolve(undefined);
67
+ return;
68
+ }
69
+ const n = stdout.split(/\r?\n/).filter((l) => l.length > 0).length;
70
+ resolve(n);
71
+ });
72
+ });
73
+ }