@danmoisan/drm-copilot-mcp 1.1.11 → 1.1.12

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 (52) hide show
  1. package/out/mcp-server.js +366 -159
  2. package/package.json +1 -1
  3. package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +1 -1
  4. package/resources/claude-customizations/.claude/agents/epic-planner.md +4 -1
  5. package/resources/claude-customizations/.claude/agents/pr-author.md +15 -0
  6. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-authorization.ps1 +443 -0
  7. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +33 -37
  8. package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +120 -5
  9. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +127 -0
  10. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +163 -15
  11. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +14 -27
  12. package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +66 -5
  13. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +134 -10
  14. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.epic-base-branch.ps1 +37 -8
  15. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.ps1 +3 -1
  16. package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner-helpers.ps1 +332 -0
  17. package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner.ps1 +211 -182
  18. package/resources/claude-customizations/.claude/lib/codex-routing/CodexDeployment.psm1 +1 -0
  19. package/resources/claude-customizations/.claude/lib/worktree-resolution/EpicScopeReadiness.psm1 +176 -0
  20. package/resources/claude-customizations/.claude/lib/worktree-resolution/EpicScopeResolution.psm1 +369 -0
  21. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeItemResolution.psm1 +392 -0
  22. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeResolution.psm1 +500 -0
  23. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeTargetResolution.psm1 +347 -0
  24. package/resources/claude-customizations/.claude/rules/orchestrator-state.md +27 -0
  25. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +12 -0
  26. package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +14 -1
  27. package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +4 -0
  28. package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +4 -1
  29. package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +39 -6
  30. package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +15 -0
  31. package/resources/claude-customizations/.claude/skills/quota-throttling/SKILL.md +221 -0
  32. package/resources/claude-customizations/pack-manifests/core.json +9 -0
  33. package/resources/codex-and-agents-customizations/.agents/skills/codex-model-routing/SKILL.md +13 -14
  34. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  35. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +193 -0
  36. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-planning-only.ps1 +15 -5
  37. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +163 -15
  38. package/resources/codex-and-agents-customizations/.codex/scripts/Resolve-CodexDeployment.ps1 +87 -0
  39. package/resources/codex-and-agents-customizations/.codex/scripts/Resolve-CodexTopology.ps1 +96 -0
  40. package/resources/codex-and-agents-customizations/.codex/scripts/codex-routing-cli-common.ps1 +370 -0
  41. package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-launch-contract.ps1 +475 -0
  42. package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-launch-runtime.ps1 +445 -0
  43. package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-persistence-runtime.ps1 +118 -0
  44. package/resources/codex-and-agents-customizations/.codex/scripts/epic-child-sandbox-preflight.ps1 +69 -0
  45. package/resources/codex-and-agents-customizations/.codex/scripts/launch-epic-child-wave.ps1 +471 -0
  46. package/resources/codex-and-agents-customizations/.codex/scripts/post-codex-worktree-session.ps1 +280 -0
  47. package/resources/codex-and-agents-customizations/.codex/scripts/resume-epic-child.ps1 +263 -0
  48. package/resources/codex-and-agents-customizations/.codex-variants/csharp-legacy/agents/csharp-typed-engineer.toml +2 -1
  49. package/resources/codex-and-agents-customizations/pack-manifests/core.json +18 -1
  50. package/resources/lib/codex-routing/CodexDeployment.psm1 +315 -0
  51. package/resources/lib/codex-routing/CodexTopology.psm1 +394 -0
  52. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +26 -0
package/out/mcp-server.js CHANGED
@@ -16321,12 +16321,14 @@ function resolveCollectCommitContextToolInput(rawInput, fallbackWorkspaceRoot) {
16321
16321
  }
16322
16322
  function resolveCollectPrContextToolInput(rawInput, fallbackWorkspaceRoot) {
16323
16323
  const args = asToolArgumentObject(rawInput);
16324
+ const targetRef = normalizeOptionalText(args["target_ref"], "target_ref");
16324
16325
  return {
16325
16326
  workspaceRoot: normalizeWorkspaceRoot(
16326
16327
  args["workspace_root"],
16327
16328
  fallbackWorkspaceRoot
16328
16329
  ),
16329
- base: normalizeRequiredText(args["base"], "base")
16330
+ base: normalizeRequiredText(args["base"], "base"),
16331
+ ...targetRef === void 0 ? {} : { targetRef }
16330
16332
  };
16331
16333
  }
16332
16334
  function resolveRunCodexNativeConverterToolInput(rawInput, fallbackWorkspaceRoot) {
@@ -17163,6 +17165,10 @@ var REPO_AUTOMATION_TOOL_DEFINITIONS = [
17163
17165
  base: {
17164
17166
  type: "string",
17165
17167
  description: "Explicit base branch or ref used for PR context collection."
17168
+ },
17169
+ target_ref: {
17170
+ type: "string",
17171
+ description: "Optional explicit head ref naming the branch to collect PR context for. When omitted, the invoking session's current HEAD is used as a fallback, and the fallback is recorded on the returned result and in the summary artifact."
17166
17172
  }
17167
17173
  },
17168
17174
  required: ["workspace_root", "base"],
@@ -17880,6 +17886,9 @@ function toMcpToolResult(result) {
17880
17886
  ...result.destinationPath === void 0 ? {} : { destination_path: result.destinationPath },
17881
17887
  ...result.renderedTree === void 0 ? {} : { rendered_tree: result.renderedTree },
17882
17888
  ...result.targetRepository === void 0 ? {} : { target_repository: result.targetRepository },
17889
+ ...result.targetResolution === void 0 ? {} : { target_resolution: result.targetResolution },
17890
+ ...result.resolvedHeadRef === void 0 ? {} : { resolved_head_ref: result.resolvedHeadRef },
17891
+ ...result.resolvedHeadSha === void 0 ? {} : { resolved_head_sha: result.resolvedHeadSha },
17883
17892
  ...result.warnings === void 0 ? {} : { warnings: result.warnings }
17884
17893
  };
17885
17894
  }
@@ -18922,9 +18931,32 @@ var ARTIFACT_DIRECTORY3 = "artifacts/codex-and-agents-customizations";
18922
18931
  var ROOT_FOLDERS = [".codex", ".agents"];
18923
18932
  var PACK_MANIFEST_SUBDIR = "pack-manifests";
18924
18933
  var ROUTING_CONFIG_RELATIVE_PATH = "config/orchestration-routing.json";
18934
+ var VIRTUAL_RESOURCE_PAIRS = [
18935
+ [ROUTING_CONFIG_RELATIVE_PATH, ROUTING_CONFIG_RELATIVE_PATH],
18936
+ [
18937
+ "config/orchestration-handoff-registry.json",
18938
+ "config/orchestration-handoff-registry.json"
18939
+ ],
18940
+ [
18941
+ "config/orchestration-handoff.schema.json",
18942
+ "config/orchestration-handoff.schema.json"
18943
+ ],
18944
+ [
18945
+ ".codex/lib/codex-routing/CodexTopology.psm1",
18946
+ "lib/codex-routing/CodexTopology.psm1"
18947
+ ],
18948
+ [
18949
+ ".codex/lib/codex-routing/CodexDeployment.psm1",
18950
+ "lib/codex-routing/CodexDeployment.psm1"
18951
+ ]
18952
+ ];
18953
+ var VIRTUAL_ROOT_FOLDERS = [
18954
+ "config",
18955
+ ".codex/lib/codex-routing"
18956
+ ];
18925
18957
  var PUBLISHED_ROOT_FOLDERS = [
18926
18958
  ...ROOT_FOLDERS,
18927
- "config"
18959
+ ...VIRTUAL_ROOT_FOLDERS
18928
18960
  ];
18929
18961
  function passthroughRewrite(text2) {
18930
18962
  return [text2, 0, 0, []];
@@ -19010,36 +19042,46 @@ var CodexFilteringFileSystem = class {
19010
19042
  var RoutingConfigFileSystem = class {
19011
19043
  constructor(inner, options) {
19012
19044
  this.inner = inner;
19013
- this.virtualPath = joinPosix4(
19014
- options.sourceRoot,
19015
- ROUTING_CONFIG_RELATIVE_PATH
19045
+ const resourceRoot = parentPosix(options.bundleRoot);
19046
+ this.virtualPaths = new Map(
19047
+ VIRTUAL_RESOURCE_PAIRS.map(
19048
+ ([destination, resource]) => [
19049
+ joinPosix4(options.sourceRoot, destination),
19050
+ joinPosix4(resourceRoot, resource)
19051
+ ]
19052
+ )
19016
19053
  );
19017
- this.virtualRoot = joinPosix4(options.sourceRoot, "config");
19018
- this.resourcePath = joinPosix4(
19019
- parentPosix(options.bundleRoot),
19020
- ROUTING_CONFIG_RELATIVE_PATH
19054
+ this.virtualRoots = new Set(
19055
+ VIRTUAL_ROOT_FOLDERS.map((root) => joinPosix4(options.sourceRoot, root))
19021
19056
  );
19022
19057
  }
19023
19058
  inner;
19024
- virtualPath;
19025
- virtualRoot;
19026
- resourcePath;
19059
+ virtualPaths;
19060
+ virtualRoots;
19061
+ resolve(path16) {
19062
+ return this.virtualPaths.get(normalizePosix(path16)) ?? path16;
19063
+ }
19027
19064
  listFiles(root) {
19028
- if (normalizePosix(root) === this.virtualRoot) {
19029
- return this.inner.isFile(this.resourcePath) ? [this.virtualPath] : [];
19065
+ const normalizedRoot = normalizePosix(root);
19066
+ if (!this.virtualRoots.has(normalizedRoot)) {
19067
+ return this.inner.listFiles(root);
19030
19068
  }
19031
- return this.inner.listFiles(root);
19069
+ const listed = [];
19070
+ for (const [virtualPath, resourcePath] of this.virtualPaths) {
19071
+ if (parentPosix(virtualPath) === normalizedRoot && this.inner.isFile(resourcePath)) {
19072
+ listed.push(virtualPath);
19073
+ }
19074
+ }
19075
+ return listed;
19032
19076
  }
19033
19077
  isDir(path16) {
19034
19078
  return this.inner.isDir(path16);
19035
19079
  }
19036
19080
  isFile(path16) {
19037
- return normalizePosix(path16) === this.virtualPath ? this.inner.isFile(this.resourcePath) : this.inner.isFile(path16);
19081
+ return this.inner.isFile(this.resolve(path16));
19038
19082
  }
19039
19083
  readTextFile(path16) {
19040
- return this.inner.readTextFile(
19041
- normalizePosix(path16) === this.virtualPath ? this.resourcePath : path16
19042
- );
19084
+ return this.inner.readTextFile(this.resolve(path16));
19043
19085
  }
19044
19086
  writeTextFile(path16, content) {
19045
19087
  this.inner.writeTextFile(path16, content);
@@ -31774,8 +31816,8 @@ function isInsidersSession(envLookup) {
31774
31816
  return false;
31775
31817
  }
31776
31818
  function resolveCodeCli(whichLookup, envLookup) {
31777
- const candidateNames = isInsidersSession(envLookup) ? ["code-insiders", "code"] : ["code", "code-insiders"];
31778
- for (const candidateName of candidateNames) {
31819
+ const candidateNames2 = isInsidersSession(envLookup) ? ["code-insiders", "code"] : ["code", "code-insiders"];
31820
+ for (const candidateName of candidateNames2) {
31779
31821
  const resolvedCommand = whichLookup(candidateName);
31780
31822
  if (resolvedCommand) {
31781
31823
  return resolvedCommand;
@@ -31894,7 +31936,56 @@ function newPotentialBugEntryServiceCall(input) {
31894
31936
  }
31895
31937
 
31896
31938
  // ../../extensions/drm-copilot/src/lib/pr-context/pr-context-service-call.ts
31939
+ var import_node_path2 = require("node:path");
31940
+
31941
+ // ../../extensions/drm-copilot/src/lib/executable-resolver.ts
31942
+ var import_node_fs = require("node:fs");
31897
31943
  var import_node_path = require("node:path");
31944
+ var DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD";
31945
+ function splitNonEmpty(value, delimiter4) {
31946
+ return value.split(delimiter4).filter((entry) => entry.length > 0);
31947
+ }
31948
+ function candidateNames(name, platform, pathExtValue) {
31949
+ if (platform !== "win32") {
31950
+ return [name];
31951
+ }
31952
+ const extensions = splitNonEmpty(
31953
+ pathExtValue === void 0 || pathExtValue === "" ? DEFAULT_PATHEXT : pathExtValue,
31954
+ ";"
31955
+ );
31956
+ const lowerName = name.toLowerCase();
31957
+ const hasKnownExtension = extensions.some(
31958
+ (ext) => lowerName.endsWith(ext.toLowerCase())
31959
+ );
31960
+ const withExtensions = extensions.map((ext) => `${name}${ext}`);
31961
+ return hasKnownExtension ? [name, ...withExtensions] : withExtensions;
31962
+ }
31963
+ function resolveExecutableOnPath(options) {
31964
+ const { name, pathValue, pathExtValue, platform, exists } = options;
31965
+ if (pathValue === void 0 || pathValue === "") {
31966
+ return void 0;
31967
+ }
31968
+ const pathApi = platform === "win32" ? import_node_path.win32 : import_node_path.posix;
31969
+ const names = candidateNames(name, platform, pathExtValue);
31970
+ for (const directory of splitNonEmpty(pathValue, pathApi.delimiter)) {
31971
+ for (const candidateName of names) {
31972
+ const candidate = pathApi.join(directory, candidateName);
31973
+ if (exists(candidate)) {
31974
+ return candidate;
31975
+ }
31976
+ }
31977
+ }
31978
+ return void 0;
31979
+ }
31980
+ function defaultWhichGh() {
31981
+ return resolveExecutableOnPath({
31982
+ name: "gh",
31983
+ pathValue: process.env["PATH"],
31984
+ pathExtValue: process.env["PATHEXT"],
31985
+ platform: process.platform,
31986
+ exists: import_node_fs.existsSync
31987
+ });
31988
+ }
31898
31989
 
31899
31990
  // ../../extensions/drm-copilot/src/lib/pr-context/models.ts
31900
31991
  var SECTION_LINE = "===== {title} =====";
@@ -31910,6 +32001,9 @@ var CONVENTIONAL_TYPES = [
31910
32001
  "ci",
31911
32002
  "style"
31912
32003
  ];
32004
+ var ISSUE_REFERENCE_PATTERN = /(?<!\w)#\d+(?!\w)/u;
32005
+ var AUTOCLOSE_UNVERIFIED_ANNOTATION = "Unverified: the issues listed above come from feature metadata only and were not checked against GitHub (GitHub CLI unavailable).";
32006
+ var AUTOCLOSE_PENDING_NOT_OPEN_TEXT = "None (deterministic pending issue is not an open issue)";
31913
32007
  function section(title) {
31914
32008
  return "\n" + SECTION_LINE.replace("{title}", title) + "\n";
31915
32009
  }
@@ -32658,6 +32752,149 @@ function isRecord5(value) {
32658
32752
  return typeof value === "object" && value !== null && !Array.isArray(value);
32659
32753
  }
32660
32754
 
32755
+ // ../../extensions/drm-copilot/src/lib/pr-context/autoclose.ts
32756
+ function classifyReferences(options) {
32757
+ const {
32758
+ gh,
32759
+ ghAvailable,
32760
+ featureIssueRefs,
32761
+ branchRefs,
32762
+ pathRefs,
32763
+ referencedIssuesSet,
32764
+ referencedPrsSet,
32765
+ invalidRefsSet
32766
+ } = options;
32767
+ if (ghAvailable) {
32768
+ for (const ref of featureIssueRefs) {
32769
+ classifyOne(
32770
+ gh,
32771
+ ref,
32772
+ referencedIssuesSet,
32773
+ referencedPrsSet,
32774
+ invalidRefsSet
32775
+ );
32776
+ }
32777
+ for (const ref of [...branchRefs, ...pathRefs]) {
32778
+ classifyOne(
32779
+ gh,
32780
+ ref,
32781
+ referencedIssuesSet,
32782
+ referencedPrsSet,
32783
+ invalidRefsSet
32784
+ );
32785
+ }
32786
+ } else {
32787
+ for (const ref of featureIssueRefs) {
32788
+ referencedIssuesSet.add(formatRef(ref));
32789
+ }
32790
+ for (const ref of [...branchRefs, ...pathRefs]) {
32791
+ referencedIssuesSet.add(formatRef(ref));
32792
+ }
32793
+ }
32794
+ }
32795
+ function classifyOne(gh, ref, issuesSet, prsSet, invalidSet) {
32796
+ const formatted = formatRef(ref);
32797
+ const entity = gh.classifyEntity(ref.replace(/^#+/u, ""));
32798
+ if (entity === "issue") {
32799
+ issuesSet.add(formatted);
32800
+ } else if (entity === "pull") {
32801
+ prsSet.add(formatted);
32802
+ } else {
32803
+ invalidSet.add(formatted);
32804
+ }
32805
+ }
32806
+ function formatRef(ref) {
32807
+ return ref.startsWith("#") ? ref : `#${ref}`;
32808
+ }
32809
+ function selectPendingPrimary(options) {
32810
+ const { gh, ghAvailable, pendingPrimary } = options;
32811
+ if (!ghAvailable) {
32812
+ return {
32813
+ kept: [...pendingPrimary],
32814
+ excluded: false,
32815
+ fetchedDetails: /* @__PURE__ */ new Map()
32816
+ };
32817
+ }
32818
+ const kept = [];
32819
+ const fetchedDetails = /* @__PURE__ */ new Map();
32820
+ let excluded = false;
32821
+ for (const ref of pendingPrimary) {
32822
+ const numberRef = normalizeReference(ref);
32823
+ if (gh.classifyEntity(numberRef) !== "issue") {
32824
+ excluded = true;
32825
+ continue;
32826
+ }
32827
+ const details = gh.issueDetails(numberRef);
32828
+ fetchedDetails.set(ref, details);
32829
+ if (details.state.toLowerCase() === "open") {
32830
+ kept.push(ref);
32831
+ } else {
32832
+ excluded = true;
32833
+ }
32834
+ }
32835
+ return { kept, excluded, fetchedDetails };
32836
+ }
32837
+ function buildCloseCandidatesSection(params) {
32838
+ const { verified, authorAsserted, referenced, verifiedReason, authorReason } = params;
32839
+ const authorAutoClose = [...new Set(authorAsserted)].sort(compareCodePoint2);
32840
+ const closing = /* @__PURE__ */ new Set([...verified, ...authorAsserted]);
32841
+ const referencedOnly = [...new Set(referenced)].filter((ref) => !closing.has(ref)).sort(compareCodePoint2);
32842
+ return [
32843
+ section("Close candidates"),
32844
+ "Auto-close issues (verified from GitHub PR metadata):",
32845
+ formatList(verified, verifiedReason),
32846
+ "",
32847
+ "Auto-close issues (author asserted):",
32848
+ formatList(authorAutoClose, authorReason),
32849
+ "",
32850
+ "Referenced issues (detected):",
32851
+ formatList(referencedOnly, "(none)")
32852
+ ].join("\n");
32853
+ }
32854
+ function buildIssuesToAutocloseSection(params) {
32855
+ const {
32856
+ verified,
32857
+ pendingPrimary,
32858
+ readinessSignals,
32859
+ ghAvailable = true,
32860
+ pendingPrimaryExcluded = false
32861
+ } = params;
32862
+ const ordered = [];
32863
+ for (const issue2 of [...verified, ...pendingPrimary]) {
32864
+ if (issue2 && !ordered.includes(issue2)) {
32865
+ ordered.push(issue2);
32866
+ }
32867
+ }
32868
+ let body;
32869
+ if (ordered.length > 0) {
32870
+ body = formatList(ordered, "(none)");
32871
+ if (!ghAvailable) {
32872
+ body = `${body}
32873
+ ${AUTOCLOSE_UNVERIFIED_ANNOTATION}`;
32874
+ }
32875
+ } else if (!ghAvailable) {
32876
+ body = "None (GitHub CLI unavailable; closing issues not verified)";
32877
+ } else if (pendingPrimaryExcluded) {
32878
+ body = AUTOCLOSE_PENDING_NOT_OPEN_TEXT;
32879
+ } else if (readinessSignals.some((signal) => signal === "PASS")) {
32880
+ body = "None (no verified closing issues and no deterministic pending issue)";
32881
+ } else {
32882
+ body = "None (no verified closing issues and readiness not PASS)";
32883
+ }
32884
+ return [section("Issues to autoclose (verified or pending)"), body].join(
32885
+ "\n"
32886
+ );
32887
+ }
32888
+ function compareCodePoint2(left, right) {
32889
+ if (left < right) {
32890
+ return -1;
32891
+ }
32892
+ if (left > right) {
32893
+ return 1;
32894
+ }
32895
+ return 0;
32896
+ }
32897
+
32661
32898
  // ../../extensions/drm-copilot/src/lib/pr-context/render-pr-helpers.ts
32662
32899
  var DEFAULT_BASE_CANDIDATES = [
32663
32900
  "origin/main",
@@ -32724,14 +32961,14 @@ function extensionSummary(files) {
32724
32961
  const ext = suffix2 ? suffix2 : "(noext)";
32725
32962
  counts.set(ext, (counts.get(ext) ?? 0) + 1);
32726
32963
  }
32727
- const lines = [...counts.keys()].sort(compareCodePoint2).map((key) => `${padCount(counts.get(key))} ${key}`);
32964
+ const lines = [...counts.keys()].sort(compareCodePoint3).map((key) => `${padCount(counts.get(key))} ${key}`);
32728
32965
  return lines.join("\n");
32729
32966
  }
32730
32967
  function extractIssueReferences(text2) {
32731
32968
  if (!text2) {
32732
32969
  return [];
32733
32970
  }
32734
- const matches = text2.match(/(?<!\w)#\d+|\b[A-Z][A-Z0-9]+-\d+\b/gu) ?? [];
32971
+ const matches = text2.match(new RegExp(ISSUE_REFERENCE_PATTERN, "gu")) ?? [];
32735
32972
  const seen = /* @__PURE__ */ new Set();
32736
32973
  const ordered = [];
32737
32974
  for (const item of matches) {
@@ -32751,7 +32988,7 @@ function extractMergePrNumbers(subjects) {
32751
32988
  numbers.add(`#${match[1]}`);
32752
32989
  }
32753
32990
  }
32754
- return [...numbers].sort(compareCodePoint2);
32991
+ return [...numbers].sort(compareCodePoint3);
32755
32992
  }
32756
32993
  function summarizeConventionalCommits(subjects) {
32757
32994
  const counts = /* @__PURE__ */ new Map();
@@ -32775,43 +33012,6 @@ function summarizeConventionalCommits(subjects) {
32775
33012
  }
32776
33013
  return nonZero.map(([name, value]) => `${padName(name)} : ${value}`).join("\n");
32777
33014
  }
32778
- function buildCloseCandidatesSection(params) {
32779
- const { verified, authorAsserted, referenced, verifiedReason, authorReason } = params;
32780
- const allAutoClose = /* @__PURE__ */ new Set([...verified, ...authorAsserted, ...referenced]);
32781
- const authorAutoClose = [...allAutoClose].sort(compareCodePoint2);
32782
- const referencedOnly = referenced.filter((ref) => !allAutoClose.has(ref)).filter((ref, index, arr) => arr.indexOf(ref) === index).sort(compareCodePoint2);
32783
- return [
32784
- section("Close candidates"),
32785
- "Auto-close issues (verified from GitHub PR metadata):",
32786
- formatList(verified, verifiedReason),
32787
- "",
32788
- "Auto-close issues (author asserted):",
32789
- formatList(authorAutoClose, authorReason),
32790
- "",
32791
- "Referenced issues (detected):",
32792
- formatList(referencedOnly, "(none)")
32793
- ].join("\n");
32794
- }
32795
- function buildIssuesToAutocloseSection(params) {
32796
- const { verified, pendingPrimary, readinessSignals } = params;
32797
- const ordered = [];
32798
- for (const issue2 of [...verified, ...pendingPrimary]) {
32799
- if (issue2 && !ordered.includes(issue2)) {
32800
- ordered.push(issue2);
32801
- }
32802
- }
32803
- let body;
32804
- if (ordered.length > 0) {
32805
- body = formatList(ordered, "(none)");
32806
- } else if (readinessSignals.some((signal) => signal === "PASS")) {
32807
- body = "None (no verified closing issues and no deterministic pending issue)";
32808
- } else {
32809
- body = "None (no verified closing issues and readiness not PASS)";
32810
- }
32811
- return [section("Issues to autoclose (verified or pending)"), body].join(
32812
- "\n"
32813
- );
32814
- }
32815
33015
  function extractChangedPaths(contextText) {
32816
33016
  const paths = [];
32817
33017
  let capture = false;
@@ -32852,7 +33052,7 @@ function padName(name) {
32852
33052
  function isDigits(value) {
32853
33053
  return value.length > 0 && /^\d+$/u.test(value);
32854
33054
  }
32855
- function compareCodePoint2(left, right) {
33055
+ function compareCodePoint3(left, right) {
32856
33056
  if (left < right) {
32857
33057
  return -1;
32858
33058
  }
@@ -33087,9 +33287,9 @@ function errorMessage(exc) {
33087
33287
  return exc instanceof Error ? exc.message : String(exc);
33088
33288
  }
33089
33289
  function sortedSet2(values) {
33090
- return [...new Set(values)].sort(compareCodePoint3);
33290
+ return [...new Set(values)].sort(compareCodePoint4);
33091
33291
  }
33092
- function compareCodePoint3(left, right) {
33292
+ function compareCodePoint4(left, right) {
33093
33293
  if (left < right) {
33094
33294
  return -1;
33095
33295
  }
@@ -33139,7 +33339,7 @@ function extractIssueReferences2(text2) {
33139
33339
  if (!text2) {
33140
33340
  return [];
33141
33341
  }
33142
- const matches = text2.match(/(?<!\w)#\d+|\b[A-Z][A-Z0-9]+-\d+\b/gu) ?? [];
33342
+ const matches = text2.match(new RegExp(ISSUE_REFERENCE_PATTERN, "gu")) ?? [];
33143
33343
  const seen = /* @__PURE__ */ new Set();
33144
33344
  const ordered = [];
33145
33345
  for (const item of matches) {
@@ -33184,7 +33384,7 @@ function readText(fs12, path16) {
33184
33384
  return fs12.exists(path16) ? fs12.readTextFile(path16) : "";
33185
33385
  }
33186
33386
  function latestGlobPath(fs12, directory, pattern) {
33187
- const matches = [...fs12.glob(directory, pattern)].sort(compareCodePoint4);
33387
+ const matches = [...fs12.glob(directory, pattern)].sort(compareCodePoint5);
33188
33388
  return matches.length > 0 ? matches[matches.length - 1] : null;
33189
33389
  }
33190
33390
  function verificationText(planText) {
@@ -33228,7 +33428,7 @@ function parseReadinessValue(text2) {
33228
33428
  }
33229
33429
  function resolveReadinessSignal(fs12, featureDir) {
33230
33430
  const auditFiles = [...fs12.glob(featureDir, "feature-audit.*.md")].sort(
33231
- compareCodePoint4
33431
+ compareCodePoint5
33232
33432
  );
33233
33433
  for (let index = auditFiles.length - 1; index >= 0; index -= 1) {
33234
33434
  const auditPath = auditFiles[index];
@@ -33247,7 +33447,7 @@ function relativeToPosix6(root, path16) {
33247
33447
  }
33248
33448
  return normalized.replace(/^\/+/u, "");
33249
33449
  }
33250
- function compareCodePoint4(left, right) {
33450
+ function compareCodePoint5(left, right) {
33251
33451
  if (left < right) {
33252
33452
  return -1;
33253
33453
  }
@@ -33285,7 +33485,7 @@ function discoverCanonicalEvidenceFiles(fs12, root, feature) {
33285
33485
  }
33286
33486
  }
33287
33487
  }
33288
- return [...discovered].sort(compareCodePoint5);
33488
+ return [...discovered].sort(compareCodePoint6);
33289
33489
  }
33290
33490
  function parseVerificationEvidenceMarkdown(params) {
33291
33491
  const { feature, sourceFile, markdown } = params;
@@ -33381,7 +33581,7 @@ function relativeToPosix7(root, absolute) {
33381
33581
  }
33382
33582
  return normalized.replace(/^\/+/u, "");
33383
33583
  }
33384
- function compareCodePoint5(left, right) {
33584
+ function compareCodePoint6(left, right) {
33385
33585
  if (left < right) {
33386
33586
  return -1;
33387
33587
  }
@@ -33429,7 +33629,7 @@ function gatherFeatureExcerpts2(fs12, root, changedFiles) {
33429
33629
  const excerpts = [];
33430
33630
  const baseDir = `${normalizedRoot}/docs/features/active`;
33431
33631
  const promotedDir = `${normalizedRoot}/docs/features/potential/promoted`;
33432
- for (const feature of [...features].sort(compareCodePoint4)) {
33632
+ for (const feature of [...features].sort(compareCodePoint5)) {
33433
33633
  const featureDir = resolveFeatureDir2(fs12, baseDir, feature);
33434
33634
  const promotedFeatureDir = resolveFeatureDir2(fs12, promotedDir, feature);
33435
33635
  if (featureDir === null && promotedFeatureDir === null) {
@@ -33583,7 +33783,7 @@ function buildContextFiles(params) {
33583
33783
  feature
33584
33784
  );
33585
33785
  return [.../* @__PURE__ */ new Set([...contextFiles, ...evidenceContextFiles])].sort(
33586
- compareCodePoint4
33786
+ compareCodePoint5
33587
33787
  );
33588
33788
  }
33589
33789
 
@@ -33884,6 +34084,29 @@ function bucketText(name, entries) {
33884
34084
  ];
33885
34085
  return lines.join("\n");
33886
34086
  }
34087
+ function buildBaseHeadSection(ctx, head, workspaceRoot) {
34088
+ const lines = [
34089
+ section("Base/Head"),
34090
+ `Base ref (requested): ${ctx.baseRef ?? "(default)"}`,
34091
+ `Base ref (resolved): ${ctx.resolvedBase ?? "(unknown)"} @ ${ctx.baseSha ?? "(unknown)"}`,
34092
+ `Head ref (resolved): ${ctx.headRef ?? head ?? "(unknown)"} @ ${ctx.headSha ?? "(unknown)"}`,
34093
+ renderHeadRefSourceLine(head, workspaceRoot),
34094
+ `Merge base: ${ctx.mergeBase ?? "(unknown)"}`,
34095
+ `Range: ${ctx.revRange ?? "(unknown)"}`
34096
+ ];
34097
+ if (ctx.baseRef && ctx.resolvedBase && !ctx.resolvedBase.startsWith("origin/")) {
34098
+ lines.push(
34099
+ `WARNING: Requested base is local and may be stale; prefer origin/${ctx.baseRef}`
34100
+ );
34101
+ }
34102
+ return lines;
34103
+ }
34104
+ function renderHeadRefSourceLine(head, workspaceRoot) {
34105
+ if (head !== null) {
34106
+ return `Head ref (source): explicit target '${head}'`;
34107
+ }
34108
+ return `Head ref (source): session fallback (no target_ref supplied; derived from workspace root '${workspaceRoot}')`;
34109
+ }
33887
34110
  function parseSection3(markdown, heading) {
33888
34111
  const escaped = heading.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
33889
34112
  const pattern = new RegExp(
@@ -33996,11 +34219,11 @@ function collectPrContext(options) {
33996
34219
  referencedPrsSet,
33997
34220
  invalidRefsSet
33998
34221
  });
33999
- const referencedIssues = [...referencedIssuesSet].sort(compareCodePoint6);
34000
- const referencedPrs = [...referencedPrsSet].sort(compareCodePoint6);
34001
- const invalidRefs = [...invalidRefsSet].sort(compareCodePoint6);
34002
- let authorAsserted = [];
34003
- const authorReasonInitial = "None (author has not asserted autoclose issues)";
34222
+ const referencedIssues = [...referencedIssuesSet].sort(compareCodePoint7);
34223
+ const referencedPrs = [...referencedPrsSet].sort(compareCodePoint7);
34224
+ const invalidRefs = [...invalidRefsSet].sort(compareCodePoint7);
34225
+ const authorAsserted = [];
34226
+ const authorReason = "None (author has not asserted autoclose issues)";
34004
34227
  const verified = ghAvailable ? contextResult.verifiedClosing : [];
34005
34228
  let verifiedReason;
34006
34229
  if (!ghAvailable) {
@@ -34012,11 +34235,6 @@ function collectPrContext(options) {
34012
34235
  } else {
34013
34236
  verifiedReason = "(verified from GitHub PR metadata)";
34014
34237
  }
34015
- let authorReason = authorReasonInitial;
34016
- if (referencedIssues.length > 0) {
34017
- authorAsserted = sortedSet3([...authorAsserted, ...referencedIssues]);
34018
- authorReason = "Detected issue references (classified)";
34019
- }
34020
34238
  const pendingPrimary = [];
34021
34239
  for (const featureDoc of featureDocs) {
34022
34240
  if (featureDoc.readinessSignal !== "PASS") {
@@ -34032,20 +34250,25 @@ function collectPrContext(options) {
34032
34250
  const readinessSignals = sortedSet3(
34033
34251
  featureDocs.map((doc) => doc.readinessSignal).filter((signal) => Boolean(signal))
34034
34252
  );
34253
+ const selection = selectPendingPrimary({ gh, ghAvailable, pendingPrimary });
34035
34254
  const issuesToAutocloseSection = buildIssuesToAutocloseSection({
34036
34255
  verified,
34037
- pendingPrimary,
34038
- readinessSignals
34256
+ pendingPrimary: selection.kept,
34257
+ readinessSignals,
34258
+ ghAvailable,
34259
+ pendingPrimaryExcluded: selection.excluded
34039
34260
  });
34040
34261
  const issuesToFetch = sortedSet3([
34041
34262
  ...verified,
34042
- ...authorAsserted,
34043
- ...referencedIssues
34263
+ ...referencedIssues,
34264
+ ...selection.kept
34044
34265
  ]);
34045
34266
  const issueDetails = [];
34046
34267
  if (ghAvailable) {
34047
34268
  for (const ref of issuesToFetch) {
34048
- issueDetails.push(gh.issueDetails(ref.replace(/^#+/u, "")));
34269
+ issueDetails.push(
34270
+ selection.fetchedDetails.get(ref) ?? gh.issueDetails(ref.replace(/^#+/u, ""))
34271
+ );
34049
34272
  }
34050
34273
  }
34051
34274
  const prDetailsList = [];
@@ -34141,66 +34364,13 @@ function collectPrContext(options) {
34141
34364
  head
34142
34365
  };
34143
34366
  }
34144
- function classifyReferences(options) {
34145
- const {
34146
- gh,
34147
- ghAvailable,
34148
- featureIssueRefs,
34149
- branchRefs,
34150
- pathRefs,
34151
- referencedIssuesSet,
34152
- referencedPrsSet,
34153
- invalidRefsSet
34154
- } = options;
34155
- if (ghAvailable) {
34156
- for (const ref of featureIssueRefs) {
34157
- classifyOne(
34158
- gh,
34159
- ref,
34160
- referencedIssuesSet,
34161
- referencedPrsSet,
34162
- invalidRefsSet
34163
- );
34164
- }
34165
- for (const ref of [...branchRefs, ...pathRefs]) {
34166
- classifyOne(
34167
- gh,
34168
- ref,
34169
- referencedIssuesSet,
34170
- referencedPrsSet,
34171
- invalidRefsSet
34172
- );
34173
- }
34174
- } else {
34175
- for (const ref of featureIssueRefs) {
34176
- referencedIssuesSet.add(formatRef(ref));
34177
- }
34178
- for (const ref of [...branchRefs, ...pathRefs]) {
34179
- referencedIssuesSet.add(formatRef(ref));
34180
- }
34181
- }
34182
- }
34183
- function classifyOne(gh, ref, issuesSet, prsSet, invalidSet) {
34184
- const formatted = formatRef(ref);
34185
- const entity = gh.classifyEntity(ref.replace(/^#+/u, ""));
34186
- if (entity === "issue") {
34187
- issuesSet.add(formatted);
34188
- } else if (entity === "pull") {
34189
- prsSet.add(formatted);
34190
- } else {
34191
- invalidSet.add(formatted);
34192
- }
34193
- }
34194
- function formatRef(ref) {
34195
- return ref.startsWith("#") ? ref : `#${ref}`;
34196
- }
34197
34367
  function errorMessage2(exc) {
34198
34368
  return exc instanceof Error ? exc.message : String(exc);
34199
34369
  }
34200
34370
  function sortedSet3(values) {
34201
- return [...new Set(values)].sort(compareCodePoint6);
34371
+ return [...new Set(values)].sort(compareCodePoint7);
34202
34372
  }
34203
- function compareCodePoint6(left, right) {
34373
+ function compareCodePoint7(left, right) {
34204
34374
  if (left < right) {
34205
34375
  return -1;
34206
34376
  }
@@ -34273,18 +34443,8 @@ function buildSummaryText(collected, fs12, appendixPath, generatedSection) {
34273
34443
  section("GitHub CLI status"),
34274
34444
  ghStatusText,
34275
34445
  intentBlock,
34276
- section("Base/Head"),
34277
- `Base ref (requested): ${ctx.baseRef ?? "(default)"}`,
34278
- `Base ref (resolved): ${ctx.resolvedBase ?? "(unknown)"} @ ${ctx.baseSha ?? "(unknown)"}`,
34279
- `Head ref (resolved): ${ctx.headRef ?? collected.head ?? "(unknown)"} @ ${ctx.headSha ?? "(unknown)"}`,
34280
- `Merge base: ${ctx.mergeBase ?? "(unknown)"}`,
34281
- `Range: ${ctx.revRange ?? "(unknown)"}`
34446
+ ...buildBaseHeadSection(ctx, collected.head, collected.resolvedRoot)
34282
34447
  ];
34283
- if (ctx.baseRef && ctx.resolvedBase && !ctx.resolvedBase.startsWith("origin/")) {
34284
- summarySections.push(
34285
- `WARNING: Requested base is local and may be stale; prefer origin/${ctx.baseRef}`
34286
- );
34287
- }
34288
34448
  const issueDigests = collected.issueDetails.map((detail) => issueDigest(detail)).join("\n\n");
34289
34449
  const prDigests = collected.prDetailsList.map((detail) => prDigest(detail)).join("\n\n");
34290
34450
  const featureSummary = buildFeatureSummary(collected.featureDocs);
@@ -34405,7 +34565,16 @@ function collectAndWrite(options) {
34405
34565
  const log = options.log ?? (() => void 0);
34406
34566
  log(`Wrote context summary to: ${options.out}`);
34407
34567
  log(`Wrote context appendix to: ${options.appendixOut}`);
34408
- return { summaryText, appendixText };
34568
+ const ctx = collected.contextResult;
34569
+ return {
34570
+ summaryText,
34571
+ appendixText,
34572
+ mergeBase: ctx.mergeBase,
34573
+ headSha: ctx.headSha,
34574
+ resolvedHeadRef: ctx.headRef ?? collected.head ?? null,
34575
+ resolvedBase: ctx.resolvedBase,
34576
+ changedFileCount: collected.bucketCore.length + collected.bucketRenames.length + collected.bucketDocs.length
34577
+ };
34409
34578
  }
34410
34579
  function resolveGhStatusText(collected) {
34411
34580
  let ghStatusText = collected.ghStatusOverride || collected.ghStatusMessage || "GitHub CLI authenticated.";
@@ -34474,6 +34643,25 @@ function parentDir(path16) {
34474
34643
  return index <= 0 ? "" : normalized.slice(0, index);
34475
34644
  }
34476
34645
 
34646
+ // ../../extensions/drm-copilot/src/lib/pr-context/diff-emptiness.ts
34647
+ function classifyPrContextDiffState(input) {
34648
+ if (input.mergeBase === null || input.headSha === null) {
34649
+ const attemptedHead = input.attemptedHeadRef ?? "(session HEAD)";
34650
+ const underlyingFailure = input.resolvedBase === null ? `base '${input.requestedBase}' did not resolve to a commit` : `head '${attemptedHead}' did not resolve to a commit`;
34651
+ return {
34652
+ kind: "refs-unresolved",
34653
+ message: `Could not resolve PR context refs for requested base '${input.requestedBase}' and attempted head '${attemptedHead}': ${underlyingFailure}. Correct the 'base' argument (or 'target_ref', if supplied) and retry.`
34654
+ };
34655
+ }
34656
+ if (input.changedFileCount === 0) {
34657
+ return {
34658
+ kind: "refs-resolved-no-change",
34659
+ message: `PR context diff is empty: resolved head ref '${input.resolvedHeadRef ?? "(unknown)"}' at head SHA '${input.headSha}' has no changes relative to merge base '${input.mergeBase}' and resolved base '${input.resolvedBase ?? "(unknown)"}'. This guard cannot detect a wrong target whose branch has commits ahead of the base; supply or correct 'target_ref' if this diff was not expected to be empty. The working-tree sections and the current-PR lookup remain scoped to 'workspace_root' even when 'target_ref' is supplied.`
34660
+ };
34661
+ }
34662
+ return { kind: "populated" };
34663
+ }
34664
+
34477
34665
  // ../../extensions/drm-copilot/src/lib/pr-context/pr-context-service-call.ts
34478
34666
  var SUMMARY_OUT = "artifacts/pr_context.summary.txt";
34479
34667
  var APPENDIX_OUT = "artifacts/pr_context.appendix.txt";
@@ -34496,10 +34684,10 @@ function verifyWrittenArtifact(fileSystem, artifactPath, expected) {
34496
34684
  }
34497
34685
  function collectPrContextServiceCall(input) {
34498
34686
  const summaryOut = normalizeGeneratedPath(
34499
- (0, import_node_path.join)(input.workspaceRoot, SUMMARY_OUT)
34687
+ (0, import_node_path2.join)(input.workspaceRoot, SUMMARY_OUT)
34500
34688
  );
34501
34689
  const appendixOut = normalizeGeneratedPath(
34502
- (0, import_node_path.join)(input.workspaceRoot, APPENDIX_OUT)
34690
+ (0, import_node_path2.join)(input.workspaceRoot, APPENDIX_OUT)
34503
34691
  );
34504
34692
  const rendered = collectAndWrite({
34505
34693
  base: input.base,
@@ -34510,15 +34698,33 @@ function collectPrContextServiceCall(input) {
34510
34698
  includeUntracked: true,
34511
34699
  fs: input.fileSystem,
34512
34700
  runner: input.runner,
34701
+ whichGh: input.whichGh ?? defaultWhichGh,
34702
+ ...input.targetRef === void 0 ? {} : { head: input.targetRef },
34513
34703
  ...input.log === void 0 ? {} : { log: input.log }
34514
34704
  });
34515
34705
  verifyWrittenArtifact(input.fileSystem, summaryOut, rendered.summaryText);
34516
34706
  verifyWrittenArtifact(input.fileSystem, appendixOut, rendered.appendixText);
34707
+ const targetResolution = input.targetRef === void 0 ? "session-fallback" : "explicit";
34708
+ const diffState = classifyPrContextDiffState({
34709
+ mergeBase: rendered.mergeBase,
34710
+ headSha: rendered.headSha,
34711
+ resolvedHeadRef: rendered.resolvedHeadRef,
34712
+ resolvedBase: rendered.resolvedBase,
34713
+ changedFileCount: rendered.changedFileCount,
34714
+ requestedBase: input.base,
34715
+ attemptedHeadRef: input.targetRef ?? null
34716
+ });
34717
+ if (diffState.kind !== "populated") {
34718
+ throw new Error(diffState.message);
34719
+ }
34517
34720
  return {
34518
34721
  tool: "collect_pr_context",
34519
34722
  workspaceRoot: input.workspaceRoot,
34520
34723
  summary: `Collected PR context against base '${input.base}'.`,
34521
- artifacts: [summaryOut, appendixOut]
34724
+ artifacts: [summaryOut, appendixOut],
34725
+ targetResolution,
34726
+ resolvedHeadRef: rendered.resolvedHeadRef,
34727
+ resolvedHeadSha: rendered.headSha
34522
34728
  };
34523
34729
  }
34524
34730
 
@@ -35676,8 +35882,8 @@ function isInsidersSession2(envLookup = defaultEnvLookup2) {
35676
35882
  return false;
35677
35883
  }
35678
35884
  function resolveCodeCli2(whichLookup = defaultWhichLookup2, envLookup = defaultEnvLookup2) {
35679
- const candidateNames = isInsidersSession2(envLookup) ? ["code-insiders", "code"] : ["code", "code-insiders"];
35680
- for (const candidateName of candidateNames) {
35885
+ const candidateNames2 = isInsidersSession2(envLookup) ? ["code-insiders", "code"] : ["code", "code-insiders"];
35886
+ for (const candidateName of candidateNames2) {
35681
35887
  const resolvedCommand = whichLookup(candidateName);
35682
35888
  if (resolvedCommand) {
35683
35889
  return resolvedCommand;
@@ -36998,6 +37204,7 @@ var DefaultRepoAutomationService = class {
36998
37204
  fileSystem: this.fileSystem,
36999
37205
  workspaceRoot: input.workspaceRoot,
37000
37206
  base: input.base,
37207
+ ...input.targetRef === void 0 ? {} : { targetRef: input.targetRef },
37001
37208
  log: (message) => this.output.appendLine(message)
37002
37209
  });
37003
37210
  }