@danmoisan/drm-copilot-mcp 1.0.11 → 1.0.14

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 (21) hide show
  1. package/out/mcp-server.js +585 -123
  2. package/package.json +1 -1
  3. package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +28 -3
  4. package/resources/claude-customizations/.claude/agents/epic-planner.md +121 -0
  5. package/resources/claude-customizations/.claude/agents/orchestrator.md +2 -2
  6. package/resources/claude-customizations/.claude/hooks/enforce-epic-invocation-origin.ps1 +246 -0
  7. package/resources/claude-customizations/.claude/hooks/persist-session-id.ps1 +153 -0
  8. package/resources/claude-customizations/.claude/settings.json +22 -2
  9. package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +58 -24
  10. package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +189 -0
  11. package/resources/claude-customizations/.claude/skills/epic-run/SKILL.md +38 -0
  12. package/resources/claude-customizations/.claude/skills/identify-session-id/SKILL.md +44 -0
  13. package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +21 -2
  14. package/resources/claude-customizations/.claude/skills/show-my-agent-tree/SKILL.md +39 -0
  15. package/resources/claude-customizations/pack-manifests/core.json +7 -0
  16. package/resources/config/orchestration-routing.json +21 -0
  17. package/resources/feature-templates/epic/epic-status.md +20 -0
  18. package/resources/feature-templates/epic/epic.md +79 -0
  19. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +4 -0
  20. package/resources/templates/new-claude-worktree-session.ps1 +58 -9
  21. package/resources/feature-templates/epic/initiative.md +0 -43
package/out/mcp-server.js CHANGED
@@ -8964,13 +8964,13 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
8964
8964
  }
8965
8965
  return propValues;
8966
8966
  });
8967
- const isObject8 = isObject;
8967
+ const isObject9 = isObject;
8968
8968
  const catchall = def.catchall;
8969
8969
  let value;
8970
8970
  inst._zod.parse = (payload, ctx) => {
8971
8971
  value ?? (value = _normalized.value);
8972
8972
  const input = payload.value;
8973
- if (!isObject8(input)) {
8973
+ if (!isObject9(input)) {
8974
8974
  payload.issues.push({
8975
8975
  expected: "object",
8976
8976
  code: "invalid_type",
@@ -9097,7 +9097,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
9097
9097
  return (payload, ctx) => fn(shape, payload, ctx);
9098
9098
  };
9099
9099
  let fastpass;
9100
- const isObject8 = isObject;
9100
+ const isObject9 = isObject;
9101
9101
  const jit = !globalConfig.jitless;
9102
9102
  const allowsEval2 = allowsEval;
9103
9103
  const fastEnabled = jit && allowsEval2.value;
@@ -9106,7 +9106,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
9106
9106
  inst._zod.parse = (payload, ctx) => {
9107
9107
  value ?? (value = _normalized.value);
9108
9108
  const input = payload.value;
9109
- if (!isObject8(input)) {
9109
+ if (!isObject9(input)) {
9110
9110
  payload.issues.push({
9111
9111
  expected: "object",
9112
9112
  code: "invalid_type",
@@ -15561,6 +15561,19 @@ function createBufferedOutput() {
15561
15561
  lines
15562
15562
  };
15563
15563
  }
15564
+ function getClaudeProjectsRoot(env = process.env) {
15565
+ const configDirOverride = env["CLAUDE_CONFIG_DIR"]?.trim();
15566
+ if (configDirOverride !== void 0 && configDirOverride.length > 0) {
15567
+ return path2.join(configDirOverride, "projects").replace(/\\/g, "/");
15568
+ }
15569
+ const home = env["HOME"]?.trim() || env["USERPROFILE"]?.trim();
15570
+ if (home === void 0 || home.length === 0) {
15571
+ throw new Error(
15572
+ "Cannot resolve the user-global Claude projects directory: none of CLAUDE_CONFIG_DIR, HOME, or USERPROFILE is set."
15573
+ );
15574
+ }
15575
+ return path2.join(home, ".claude", "projects").replace(/\\/g, "/");
15576
+ }
15564
15577
  function resolveBundledScriptPath(extensionRoot, bundledRelativePath) {
15565
15578
  const normalizedExtensionRoot = extensionRoot.replace(/\\/g, "/");
15566
15579
  const normalizedBundledRelativePath = bundledRelativePath.replace(/\\/g, "/").replace(/^\/+/, "");
@@ -16222,6 +16235,22 @@ var REPO_AUTOMATION_TOOL_DEFINITIONS = [
16222
16235
  required: ["artifact_type", "artifact_path"],
16223
16236
  additionalProperties: false
16224
16237
  }
16238
+ },
16239
+ {
16240
+ name: "render_subagent_tree",
16241
+ description: "Render the subagent call tree for a root session id. The session id is a transcript filename stem; the transcript is resolved under the user-global Claude projects directory, searching the encoded workspace directory plus its '-wt-' worktree siblings (case-insensitive) and returning the first match deterministically.",
16242
+ inputSchema: {
16243
+ type: "object",
16244
+ properties: {
16245
+ workspace_root: workspaceRootProperty,
16246
+ session_id: {
16247
+ type: "string",
16248
+ description: "Root session identifier (transcript filename stem under ~/.claude/projects/<encoded-workspace>/, e.g. a UUIDv4)."
16249
+ }
16250
+ },
16251
+ required: ["session_id"],
16252
+ additionalProperties: false
16253
+ }
16225
16254
  }
16226
16255
  ];
16227
16256
 
@@ -16246,7 +16275,8 @@ var REPO_AUTOMATION_TOOLS = [
16246
16275
  "resolve_policy_audit_template_asset",
16247
16276
  "resolve_execute_hard_lock_prompt",
16248
16277
  "resolve_atomic_plan_prompt",
16249
- "validate_orchestration_artifacts"
16278
+ "validate_orchestration_artifacts",
16279
+ "render_subagent_tree"
16250
16280
  ];
16251
16281
 
16252
16282
  // ../../extensions/drm-copilot/src/mcp-tool-inputs-push-down.ts
@@ -16700,6 +16730,24 @@ async function handleResolveExecuteHardLockPrompt(rawInput, service) {
16700
16730
  });
16701
16731
  }
16702
16732
 
16733
+ // ../../extensions/drm-copilot/src/mcp-tool-inputs-subagent-tree.ts
16734
+ function resolveRenderSubagentTreeToolInput(rawInput, fallbackWorkspaceRoot) {
16735
+ const args = asToolArgumentObject(rawInput);
16736
+ return {
16737
+ workspaceRoot: normalizeWorkspaceRoot(
16738
+ args["workspace_root"],
16739
+ fallbackWorkspaceRoot
16740
+ ),
16741
+ sessionId: normalizeRequiredText(args["session_id"], "session_id")
16742
+ };
16743
+ }
16744
+
16745
+ // ../../extensions/drm-copilot/src/mcp-handlers/render-subagent-tree-handler.ts
16746
+ async function handleRenderSubagentTree(rawInput, service) {
16747
+ const input = resolveRenderSubagentTreeToolInput(rawInput);
16748
+ return service.renderSubagentTree(input);
16749
+ }
16750
+
16703
16751
  // ../../extensions/drm-copilot/src/mcp-handlers/template-validation-handlers.ts
16704
16752
  async function handleResolvePolicyAuditTemplateAsset(rawInput, service) {
16705
16753
  const input = resolvePolicyAuditTemplateAssetToolInput(rawInput);
@@ -16727,7 +16775,8 @@ function toMcpToolResult(result) {
16727
16775
  ...result.artifacts === void 0 ? {} : { artifacts: result.artifacts },
16728
16776
  ...result.assetId === void 0 ? {} : { asset_id: result.assetId },
16729
16777
  ...result.bundledSourcePath === void 0 ? {} : { bundled_source_path: result.bundledSourcePath },
16730
- ...result.destinationPath === void 0 ? {} : { destination_path: result.destinationPath }
16778
+ ...result.destinationPath === void 0 ? {} : { destination_path: result.destinationPath },
16779
+ ...result.renderedTree === void 0 ? {} : { rendered_tree: result.renderedTree }
16731
16780
  };
16732
16781
  }
16733
16782
  function toFailureToolResult(tool, workspaceRoot, error2) {
@@ -16833,6 +16882,11 @@ async function dispatchRepoAutomationTool(toolName, rawInput, service) {
16833
16882
  await handleValidateOrchestrationArtifacts(rawInput, service)
16834
16883
  );
16835
16884
  }
16885
+ case "render_subagent_tree": {
16886
+ return toMcpToolResult(
16887
+ await handleRenderSubagentTree(rawInput, service)
16888
+ );
16889
+ }
16836
16890
  }
16837
16891
  } catch (error2) {
16838
16892
  return toFailureToolResult(toolName, workspaceRoot, error2);
@@ -17039,6 +17093,26 @@ function parseFirstArtifactPath(execution, pattern) {
17039
17093
  return capturedPath && capturedPath.length > 0 ? normalizeGeneratedPath(capturedPath) : void 0;
17040
17094
  }
17041
17095
 
17096
+ // ../../extensions/drm-copilot/src/repo-automation-execute-script.ts
17097
+ async function executeScriptServiceCall(output, extensionRoot, options) {
17098
+ const execution = await executeBundledScriptFromExtensionRoot(output, {
17099
+ runtimeKind: options.runtimeKind,
17100
+ bundledRelativePath: options.bundledRelativePath,
17101
+ commandId: options.invocationId,
17102
+ args: options.args,
17103
+ extensionRoot,
17104
+ workspaceRoot: options.workspaceRoot
17105
+ });
17106
+ const parsedArtifactPath = options.stdoutArtifactPattern === void 0 ? void 0 : parseFirstArtifactPath(execution, options.stdoutArtifactPattern);
17107
+ const artifacts = options.artifactPaths ?? (parsedArtifactPath === void 0 ? void 0 : [parsedArtifactPath]);
17108
+ return {
17109
+ tool: options.tool,
17110
+ workspaceRoot: options.workspaceRoot,
17111
+ summary: options.summary,
17112
+ ...artifacts === void 0 ? {} : { artifacts }
17113
+ };
17114
+ }
17115
+
17042
17116
  // ../../extensions/drm-copilot/src/repo-automation-args.ts
17043
17117
  function buildPoshQcWorkflowArguments(tool, input) {
17044
17118
  const toolConfig = POSH_QC_TOOL_CONFIG[tool];
@@ -21791,6 +21865,143 @@ var SubprocessRunner = class {
21791
21865
  // ../../extensions/drm-copilot/src/lib/validate/validate-orchestration-service-call.ts
21792
21866
  var path9 = __toESM(require("node:path"));
21793
21867
 
21868
+ // ../../extensions/drm-copilot/src/lib/validate/epic-orchestrator-state-resolution.ts
21869
+ var LIFECYCLE_PREFIXES = [
21870
+ "docs/features/active/",
21871
+ "docs/features/completed/",
21872
+ "active/",
21873
+ "completed/"
21874
+ ];
21875
+ var VALID_EPIC_TYPES = /* @__PURE__ */ new Set(["business", "enabler"]);
21876
+ function isObject2(value) {
21877
+ return typeof value === "object" && value !== null && !Array.isArray(value);
21878
+ }
21879
+ function pythonRepr(value) {
21880
+ if (value === null || value === void 0) {
21881
+ return "None";
21882
+ }
21883
+ if (typeof value === "boolean") {
21884
+ return value ? "True" : "False";
21885
+ }
21886
+ if (typeof value === "string") {
21887
+ return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
21888
+ }
21889
+ return String(value);
21890
+ }
21891
+ function normalizeFolderHint(value) {
21892
+ for (const prefix of LIFECYCLE_PREFIXES) {
21893
+ if (value.startsWith(prefix)) {
21894
+ return value.slice(prefix.length);
21895
+ }
21896
+ }
21897
+ return value;
21898
+ }
21899
+ function buildFeatureReferenceIndex(features) {
21900
+ const byFolderHint = /* @__PURE__ */ new Map();
21901
+ const byIssueNum = /* @__PURE__ */ new Map();
21902
+ for (const feature of features) {
21903
+ const folder = feature["feature_folder"];
21904
+ if (typeof folder === "string" && folder) {
21905
+ byFolderHint.set(normalizeFolderHint(folder), folder);
21906
+ const issueNum = feature["issue_num"];
21907
+ if (issueNum !== void 0 && issueNum !== null) {
21908
+ byIssueNum.set(issueNum, folder);
21909
+ }
21910
+ }
21911
+ }
21912
+ return { byFolderHint, byIssueNum };
21913
+ }
21914
+ function resolveFeatureReference(dependency, index) {
21915
+ if (typeof dependency !== "string") {
21916
+ return index.byIssueNum.get(dependency) ?? null;
21917
+ }
21918
+ return index.byFolderHint.get(normalizeFolderHint(dependency)) ?? null;
21919
+ }
21920
+ function detectDependencyCycle(features) {
21921
+ const index = buildFeatureReferenceIndex(features);
21922
+ const graph = /* @__PURE__ */ new Map();
21923
+ for (const feature of features) {
21924
+ const folder = feature["feature_folder"];
21925
+ if (typeof folder !== "string" || !folder) {
21926
+ continue;
21927
+ }
21928
+ const dependsOn = feature["depends_on"];
21929
+ if (!Array.isArray(dependsOn)) {
21930
+ graph.set(folder, []);
21931
+ continue;
21932
+ }
21933
+ const resolvedEdges = [];
21934
+ for (const dependency of dependsOn) {
21935
+ const resolved = resolveFeatureReference(dependency, index);
21936
+ if (resolved !== null) {
21937
+ resolvedEdges.push(resolved);
21938
+ }
21939
+ }
21940
+ graph.set(folder, resolvedEdges);
21941
+ }
21942
+ const visiting = /* @__PURE__ */ new Set();
21943
+ const visited = /* @__PURE__ */ new Set();
21944
+ function visit(node) {
21945
+ if (visiting.has(node)) {
21946
+ return node;
21947
+ }
21948
+ if (visited.has(node) || !graph.has(node)) {
21949
+ return null;
21950
+ }
21951
+ visiting.add(node);
21952
+ for (const dependency of graph.get(node) ?? []) {
21953
+ const cycleNode = visit(dependency);
21954
+ if (cycleNode !== null) {
21955
+ return cycleNode;
21956
+ }
21957
+ }
21958
+ visiting.delete(node);
21959
+ visited.add(node);
21960
+ return null;
21961
+ }
21962
+ for (const start of graph.keys()) {
21963
+ const cycleNode = visit(start);
21964
+ if (cycleNode !== null) {
21965
+ return `Epic checkpoint depends_on graph contains a cycle involving feature_folder: ${cycleNode}`;
21966
+ }
21967
+ }
21968
+ return null;
21969
+ }
21970
+ function validateIntentBlock(state) {
21971
+ if (!("intent" in state)) {
21972
+ return [];
21973
+ }
21974
+ const intent = state["intent"];
21975
+ if (!isObject2(intent)) {
21976
+ return ["Epic checkpoint intent must be an object."];
21977
+ }
21978
+ const errors = [];
21979
+ const epicType = intent["epic_type"];
21980
+ if (typeof epicType !== "string" || !VALID_EPIC_TYPES.has(epicType)) {
21981
+ errors.push(
21982
+ `Epic checkpoint intent.epic_type must be 'business' or 'enabler', found: ${pythonRepr(epicType)}`
21983
+ );
21984
+ }
21985
+ const hypothesis = intent["business_outcome_hypothesis"];
21986
+ if (typeof hypothesis !== "string" || !hypothesis.trim()) {
21987
+ errors.push(
21988
+ "Epic checkpoint intent.business_outcome_hypothesis must be a non-empty string."
21989
+ );
21990
+ }
21991
+ for (const fieldName of ["leading_indicators", "nfrs"]) {
21992
+ if (!(fieldName in intent)) {
21993
+ continue;
21994
+ }
21995
+ const value = intent[fieldName];
21996
+ if (!Array.isArray(value) || !value.every((item) => typeof item === "string")) {
21997
+ errors.push(
21998
+ `Epic checkpoint intent.${fieldName} must be a list of strings.`
21999
+ );
22000
+ }
22001
+ }
22002
+ return errors;
22003
+ }
22004
+
21794
22005
  // ../../extensions/drm-copilot/src/lib/validate/epic-orchestrator-state-core.ts
21795
22006
  var REQUIRED_BASELINE_KEYS = [
21796
22007
  "objective",
@@ -21820,7 +22031,7 @@ var MERGED_STATUSES = /* @__PURE__ */ new Set([
21820
22031
  "merged",
21821
22032
  "worktree_removed"
21822
22033
  ]);
21823
- function isObject2(value) {
22034
+ function isObject3(value) {
21824
22035
  return typeof value === "object" && value !== null && !Array.isArray(value);
21825
22036
  }
21826
22037
  function extractFeatures(state) {
@@ -21828,7 +22039,7 @@ function extractFeatures(state) {
21828
22039
  if (!Array.isArray(features)) {
21829
22040
  return [];
21830
22041
  }
21831
- return features.filter(isObject2);
22042
+ return features.filter(isObject3);
21832
22043
  }
21833
22044
  function missingBaselineAndEpicKeys(state) {
21834
22045
  const errors = [];
@@ -21851,13 +22062,7 @@ function validateFeatureFolderUniquenessAndDependencies(features) {
21851
22062
  const errors = [];
21852
22063
  const seen = /* @__PURE__ */ new Set();
21853
22064
  const duplicates = /* @__PURE__ */ new Set();
21854
- const allFolders = /* @__PURE__ */ new Set();
21855
- for (const feature of features) {
21856
- const folder = feature["feature_folder"];
21857
- if (typeof folder === "string" && folder) {
21858
- allFolders.add(folder);
21859
- }
21860
- }
22065
+ const index = buildFeatureReferenceIndex(features);
21861
22066
  for (const feature of features) {
21862
22067
  const folder = feature["feature_folder"];
21863
22068
  if (typeof folder !== "string" || !folder) {
@@ -21872,7 +22077,7 @@ function validateFeatureFolderUniquenessAndDependencies(features) {
21872
22077
  continue;
21873
22078
  }
21874
22079
  for (const dependency of dependsOn) {
21875
- if (!allFolders.has(dependency)) {
22080
+ if (resolveFeatureReference(dependency, index) === null) {
21876
22081
  errors.push(
21877
22082
  `Epic checkpoint feature '${folder}' depends_on unresolved feature_folder: ${JSON.stringify(dependency)}`
21878
22083
  );
@@ -21886,49 +22091,6 @@ function validateFeatureFolderUniquenessAndDependencies(features) {
21886
22091
  }
21887
22092
  return errors;
21888
22093
  }
21889
- function detectDependencyCycle(features) {
21890
- const graph = /* @__PURE__ */ new Map();
21891
- for (const feature of features) {
21892
- const folder = feature["feature_folder"];
21893
- if (typeof folder !== "string" || !folder) {
21894
- continue;
21895
- }
21896
- const dependsOn = feature["depends_on"];
21897
- graph.set(
21898
- folder,
21899
- Array.isArray(dependsOn) ? dependsOn.filter(
21900
- (d) => typeof d === "string"
21901
- ) : []
21902
- );
21903
- }
21904
- const visiting = /* @__PURE__ */ new Set();
21905
- const visited = /* @__PURE__ */ new Set();
21906
- function visit(node) {
21907
- if (visiting.has(node)) {
21908
- return node;
21909
- }
21910
- if (visited.has(node) || !graph.has(node)) {
21911
- return null;
21912
- }
21913
- visiting.add(node);
21914
- for (const dependency of graph.get(node) ?? []) {
21915
- const cycleNode = visit(dependency);
21916
- if (cycleNode !== null) {
21917
- return cycleNode;
21918
- }
21919
- }
21920
- visiting.delete(node);
21921
- visited.add(node);
21922
- return null;
21923
- }
21924
- for (const start of graph.keys()) {
21925
- const cycleNode = visit(start);
21926
- if (cycleNode !== null) {
21927
- return `Epic checkpoint depends_on graph contains a cycle involving feature_folder: ${cycleNode}`;
21928
- }
21929
- }
21930
- return null;
21931
- }
21932
22094
  function validateMergeStatusEnum(features) {
21933
22095
  const errors = [];
21934
22096
  for (const feature of features) {
@@ -21951,6 +22113,7 @@ function validateWaveBarrierOrdering(features) {
21951
22113
  byFolder.set(folder, feature);
21952
22114
  }
21953
22115
  }
22116
+ const index = buildFeatureReferenceIndex(features);
21954
22117
  for (const feature of features) {
21955
22118
  const folder = feature["feature_folder"];
21956
22119
  const dependsOn = feature["depends_on"];
@@ -21959,7 +22122,8 @@ function validateWaveBarrierOrdering(features) {
21959
22122
  }
21960
22123
  const worktreeCreatedAt = feature["worktree_created_at"];
21961
22124
  for (const dependency of dependsOn) {
21962
- const dependencyFeature = byFolder.get(dependency);
22125
+ const resolved = resolveFeatureReference(dependency, index);
22126
+ const dependencyFeature = resolved !== null ? byFolder.get(resolved) : void 0;
21963
22127
  if (dependencyFeature === void 0) {
21964
22128
  continue;
21965
22129
  }
@@ -21982,15 +22146,17 @@ function validateWavesConsistency(state) {
21982
22146
  if (!Array.isArray(waves)) {
21983
22147
  return errors;
21984
22148
  }
22149
+ const features = extractFeatures(state);
21985
22150
  const featuresByFolder = /* @__PURE__ */ new Map();
21986
- for (const feature of extractFeatures(state)) {
22151
+ for (const feature of features) {
21987
22152
  const folder = feature["feature_folder"];
21988
22153
  if (typeof folder === "string") {
21989
22154
  featuresByFolder.set(folder, feature);
21990
22155
  }
21991
22156
  }
22157
+ const index = buildFeatureReferenceIndex(features);
21992
22158
  for (const waveItem of waves) {
21993
- if (!isObject2(waveItem)) {
22159
+ if (!isObject3(waveItem)) {
21994
22160
  continue;
21995
22161
  }
21996
22162
  const waveNumber = waveItem["wave_number"];
@@ -21999,7 +22165,8 @@ function validateWavesConsistency(state) {
21999
22165
  continue;
22000
22166
  }
22001
22167
  for (const folder of folders) {
22002
- const feature = featuresByFolder.get(folder);
22168
+ const resolved = resolveFeatureReference(folder, index);
22169
+ const feature = resolved !== null ? featuresByFolder.get(resolved) : void 0;
22003
22170
  if (feature === void 0) {
22004
22171
  continue;
22005
22172
  }
@@ -22024,7 +22191,7 @@ function validateCompletion(features, state) {
22024
22191
  }
22025
22192
  }
22026
22193
  const epicMergePr = state["epic_merge_pr"];
22027
- const mergeCommitSha = isObject2(epicMergePr) ? epicMergePr["merge_commit_sha"] : void 0;
22194
+ const mergeCommitSha = isObject3(epicMergePr) ? epicMergePr["merge_commit_sha"] : void 0;
22028
22195
  if (typeof mergeCommitSha !== "string" || !mergeCommitSha.trim()) {
22029
22196
  errors.push(
22030
22197
  "Epic checkpoint completion validation failed: epic_merge_pr.merge_commit_sha is missing or empty."
@@ -22041,7 +22208,7 @@ function validateEpicOrchestratorStateText(text, options = {}) {
22041
22208
  `Epic checkpoint is not valid JSON: ${exc instanceof Error ? exc.message : String(exc)}`
22042
22209
  ];
22043
22210
  }
22044
- if (!isObject2(state)) {
22211
+ if (!isObject3(state)) {
22045
22212
  return ["Epic checkpoint root must be a JSON object."];
22046
22213
  }
22047
22214
  const stateMap = state;
@@ -22057,6 +22224,7 @@ function validateEpicOrchestratorStateText(text, options = {}) {
22057
22224
  errors.push(...validateMergeStatusEnum(features));
22058
22225
  errors.push(...validateWaveBarrierOrdering(features));
22059
22226
  errors.push(...validateWavesConsistency(stateMap));
22227
+ errors.push(...validateIntentBlock(stateMap));
22060
22228
  if (options.requireComplete === true) {
22061
22229
  errors.push(...validateCompletion(features, stateMap));
22062
22230
  }
@@ -22079,11 +22247,11 @@ var PROMOTION_RECEIPT_KEYS = [
22079
22247
  "issue",
22080
22248
  "feature_folder"
22081
22249
  ];
22082
- function isObject3(value) {
22250
+ function isObject4(value) {
22083
22251
  return typeof value === "object" && value !== null && !Array.isArray(value);
22084
22252
  }
22085
22253
  function missingObjectKeys(value, keys) {
22086
- if (!isObject3(value)) {
22254
+ if (!isObject4(value)) {
22087
22255
  return [...keys];
22088
22256
  }
22089
22257
  const missing = [];
@@ -22098,7 +22266,7 @@ function missingObjectKeys(value, keys) {
22098
22266
  function validateCompletionPrGate(state) {
22099
22267
  const prGate = state["pr_gate"];
22100
22268
  const missing = missingObjectKeys(prGate, PR_GATE_KEYS);
22101
- if (!isObject3(prGate)) {
22269
+ if (!isObject4(prGate)) {
22102
22270
  return [
22103
22271
  `Checkpoint completion validation failed: pr_gate must be an object with keys: ${PR_GATE_KEYS.join(", ")}.`
22104
22272
  ];
@@ -22121,7 +22289,7 @@ function validateCompletionPrGate(state) {
22121
22289
  function validateCompletionCiGate(state) {
22122
22290
  const ciGate = state["ci_gate"];
22123
22291
  const missing = missingObjectKeys(ciGate, CI_GATE_KEYS);
22124
- if (!isObject3(ciGate)) {
22292
+ if (!isObject4(ciGate)) {
22125
22293
  return [
22126
22294
  `Checkpoint completion validation failed: ci_gate must be an object with keys: ${CI_GATE_KEYS.join(", ")}.`
22127
22295
  ];
@@ -22138,7 +22306,7 @@ function validateCompletionCiGate(state) {
22138
22306
  );
22139
22307
  }
22140
22308
  const prGate = state["pr_gate"];
22141
- const prHeadSha = isObject3(prGate) ? prGate["head_sha"] : null;
22309
+ const prHeadSha = isObject4(prGate) ? prGate["head_sha"] : null;
22142
22310
  if (prHeadSha !== null && prHeadSha !== void 0 && ciGate["head_sha"] !== prHeadSha) {
22143
22311
  errors.push(
22144
22312
  "Checkpoint completion validation failed: ci_gate.head_sha must match pr_gate.head_sha."
@@ -22153,7 +22321,7 @@ function validateIssue232PromotionReceipts(state) {
22153
22321
  const receipts = state["delegation_receipts"];
22154
22322
  let promotionSource = "promotion_receipts";
22155
22323
  let promotion = state["promotion_receipts"];
22156
- if (isObject3(receipts)) {
22324
+ if (isObject4(receipts)) {
22157
22325
  const namespacedPromotion = receipts[PROMOTION_RECEIPT_NAMESPACE_KEY];
22158
22326
  if (namespacedPromotion !== void 0 && namespacedPromotion !== null) {
22159
22327
  promotionSource = "delegation_receipts.promotion";
@@ -22178,10 +22346,10 @@ var HUMAN_INTERACTION_RESPONSE_ENUM = /* @__PURE__ */ new Set([
22178
22346
  "halt"
22179
22347
  ]);
22180
22348
  var HUMAN_INTERACTION_EXCEPTION_RESPONSE = "exception";
22181
- function isObject4(value) {
22349
+ function isObject5(value) {
22182
22350
  return typeof value === "object" && value !== null && !Array.isArray(value);
22183
22351
  }
22184
- function pythonRepr(value) {
22352
+ function pythonRepr2(value) {
22185
22353
  if (value === null || value === void 0) {
22186
22354
  return "None";
22187
22355
  }
@@ -22195,7 +22363,7 @@ function pythonRepr(value) {
22195
22363
  }
22196
22364
  function validateHumanInteraction(humanInteraction) {
22197
22365
  const errors = [];
22198
- if (!isObject4(humanInteraction)) {
22366
+ if (!isObject5(humanInteraction)) {
22199
22367
  errors.push("Checkpoint human_interaction must be an object when present.");
22200
22368
  return errors;
22201
22369
  }
@@ -22205,7 +22373,7 @@ function validateHumanInteraction(humanInteraction) {
22205
22373
  return errors;
22206
22374
  }
22207
22375
  requirements.forEach((requirement, index) => {
22208
- if (!isObject4(requirement)) {
22376
+ if (!isObject5(requirement)) {
22209
22377
  errors.push(
22210
22378
  `Checkpoint human_interaction.requirements #${index} must be an object.`
22211
22379
  );
@@ -22214,7 +22382,7 @@ function validateHumanInteraction(humanInteraction) {
22214
22382
  const response = requirement["response"];
22215
22383
  if (typeof response !== "string" || !HUMAN_INTERACTION_RESPONSE_ENUM.has(response)) {
22216
22384
  errors.push(
22217
- `Checkpoint human_interaction.requirements #${index} response must be one of scope_change, exception, halt; got: ` + pythonRepr(response)
22385
+ `Checkpoint human_interaction.requirements #${index} response must be one of scope_change, exception, halt; got: ` + pythonRepr2(response)
22218
22386
  );
22219
22387
  return;
22220
22388
  }
@@ -22235,7 +22403,7 @@ var REMEDIATION_LOOP_KEY = "remediation_loop";
22235
22403
  var REMEDIATION_CYCLES_KEY = "cycles";
22236
22404
  var EXECUTION_STATUSES_REQUIRING_CLEAR_PREFLIGHT = /* @__PURE__ */ new Set(["in_progress", "complete", "failed"]);
22237
22405
  var PREFLIGHT_CLEARED_STATUS = "clear";
22238
- function isObject5(value) {
22406
+ function isObject6(value) {
22239
22407
  return typeof value === "object" && value !== null && !Array.isArray(value);
22240
22408
  }
22241
22409
  function validateRemediationCycle(index, cycle) {
@@ -22249,7 +22417,7 @@ function validateRemediationCycle(index, cycle) {
22249
22417
  const executionStatus = cycle["execution_status"];
22250
22418
  if (typeof executionStatus === "string" && EXECUTION_STATUSES_REQUIRING_CLEAR_PREFLIGHT.has(executionStatus)) {
22251
22419
  const preflight = cycle["preflight"];
22252
- const preflightStatus = isObject5(preflight) ? preflight["final_status"] : void 0;
22420
+ const preflightStatus = isObject6(preflight) ? preflight["final_status"] : void 0;
22253
22421
  if (preflightStatus !== PREFLIGHT_CLEARED_STATUS) {
22254
22422
  errors.push(
22255
22423
  `Checkpoint remediation cycle #${index} execution_status is ${executionStatus} but preflight.final_status is not 'clear'.`
@@ -22265,7 +22433,7 @@ function validateRemediationCycle(index, cycle) {
22265
22433
  }
22266
22434
  function validateRemediationLoop(remediationLoop) {
22267
22435
  const errors = [];
22268
- if (!isObject5(remediationLoop)) {
22436
+ if (!isObject6(remediationLoop)) {
22269
22437
  return errors;
22270
22438
  }
22271
22439
  const cycles = remediationLoop[REMEDIATION_CYCLES_KEY];
@@ -22273,7 +22441,7 @@ function validateRemediationLoop(remediationLoop) {
22273
22441
  return errors;
22274
22442
  }
22275
22443
  cycles.forEach((cycle, index) => {
22276
- if (!isObject5(cycle)) {
22444
+ if (!isObject6(cycle)) {
22277
22445
  errors.push(`Checkpoint remediation cycle #${index} must be an object.`);
22278
22446
  return;
22279
22447
  }
@@ -22284,7 +22452,7 @@ function validateRemediationLoop(remediationLoop) {
22284
22452
 
22285
22453
  // ../../extensions/drm-copilot/src/lib/validate/orchestrator-state-routing.ts
22286
22454
  var ROUTING_MATRIX_RELATIVE_PATH = "config/orchestration-routing.json";
22287
- function isObject6(value) {
22455
+ function isObject7(value) {
22288
22456
  return typeof value === "object" && value !== null && !Array.isArray(value);
22289
22457
  }
22290
22458
  function loadRoutingMatrix(fs9, root) {
@@ -22321,7 +22489,7 @@ function listReceipts(receipts) {
22321
22489
  if (!Array.isArray(receipts)) {
22322
22490
  return [];
22323
22491
  }
22324
- return receipts.filter(isObject6);
22492
+ return receipts.filter(isObject7);
22325
22493
  }
22326
22494
  function receiptAgents(state) {
22327
22495
  const agents = /* @__PURE__ */ new Set();
@@ -22340,7 +22508,7 @@ function receiptSkills(state) {
22340
22508
  return skills;
22341
22509
  }
22342
22510
  for (const receipt of receipts) {
22343
- if (!isObject6(receipt)) {
22511
+ if (!isObject7(receipt)) {
22344
22512
  continue;
22345
22513
  }
22346
22514
  const skill = receipt["skill"];
@@ -22359,7 +22527,7 @@ function mcpTools(state) {
22359
22527
  return tools;
22360
22528
  }
22361
22529
  for (const receipt of receipts) {
22362
- if (!isObject6(receipt)) {
22530
+ if (!isObject7(receipt)) {
22363
22531
  continue;
22364
22532
  }
22365
22533
  const tool = receipt["tool"];
@@ -22391,7 +22559,7 @@ function validateLifecycleOperations(state) {
22391
22559
  }
22392
22560
  const errors = [];
22393
22561
  operations.forEach((operation, index) => {
22394
- if (!isObject6(operation)) {
22562
+ if (!isObject7(operation)) {
22395
22563
  errors.push(
22396
22564
  `Checkpoint lifecycle_operations #${index} must be an object.`
22397
22565
  );
@@ -22407,11 +22575,11 @@ function validateLifecycleOperations(state) {
22407
22575
  }
22408
22576
  function validateRoutingContract(state, options = {}) {
22409
22577
  const matrix = options.routingMatrix;
22410
- if (!isObject6(matrix)) {
22578
+ if (!isObject7(matrix)) {
22411
22579
  return ["Routing matrix missing routes object."];
22412
22580
  }
22413
22581
  const rawRoutes = matrix["routes"];
22414
- if (!isObject6(rawRoutes)) {
22582
+ if (!isObject7(rawRoutes)) {
22415
22583
  return ["Routing matrix missing routes object."];
22416
22584
  }
22417
22585
  const routeIdValue = state["route_id"] !== void 0 ? state["route_id"] : state["path_selected"];
@@ -22420,7 +22588,7 @@ function validateRoutingContract(state, options = {}) {
22420
22588
  }
22421
22589
  const routeId = routeIdValue;
22422
22590
  const rawRoute = rawRoutes[routeId];
22423
- if (!isObject6(rawRoute)) {
22591
+ if (!isObject7(rawRoute)) {
22424
22592
  return [
22425
22593
  `Checkpoint selected route has no routing-matrix entry: ${routeId}.`
22426
22594
  ];
@@ -22538,13 +22706,13 @@ var DELEGATING_AGENTS = /* @__PURE__ */ new Set([
22538
22706
  "prd-feature",
22539
22707
  "pr-author"
22540
22708
  ]);
22541
- function isObject7(value) {
22709
+ function isObject8(value) {
22542
22710
  return typeof value === "object" && value !== null && !Array.isArray(value);
22543
22711
  }
22544
22712
  function validateListDelegationReceipts(receipts) {
22545
22713
  const errors = [];
22546
22714
  receipts.forEach((receipt, index) => {
22547
- if (!isObject7(receipt)) {
22715
+ if (!isObject8(receipt)) {
22548
22716
  errors.push(`Checkpoint delegation receipt #${index} must be an object.`);
22549
22717
  return;
22550
22718
  }
@@ -22576,7 +22744,7 @@ function validateNamespacedDelegationReceipts(receipts) {
22576
22744
  if (promotionReceipts === void 0 || promotionReceipts === null) {
22577
22745
  return errors;
22578
22746
  }
22579
- if (!isObject7(promotionReceipts)) {
22747
+ if (!isObject8(promotionReceipts)) {
22580
22748
  errors.push(
22581
22749
  "Checkpoint delegation_receipts.promotion must be an object namespace."
22582
22750
  );
@@ -22606,7 +22774,7 @@ function delegatedAgents(stateMap) {
22606
22774
  const receipts = stateMap["delegation_receipts"];
22607
22775
  if (Array.isArray(receipts)) {
22608
22776
  receipts.forEach((receipt) => {
22609
- if (!isObject7(receipt)) {
22777
+ if (!isObject8(receipt)) {
22610
22778
  return;
22611
22779
  }
22612
22780
  const agentName = receipt["agent_name"];
@@ -22631,7 +22799,7 @@ function validateModelRoutingExistence(stateMap) {
22631
22799
  const receipts = stateMap["model_routing_receipts"];
22632
22800
  if (Array.isArray(receipts)) {
22633
22801
  receipts.forEach((receipt) => {
22634
- if (!isObject7(receipt)) {
22802
+ if (!isObject8(receipt)) {
22635
22803
  return;
22636
22804
  }
22637
22805
  const agent = receipt["agent"];
@@ -22658,7 +22826,7 @@ function validateOrchestratorStateText(text, options = {}) {
22658
22826
  `Checkpoint is not valid JSON: ${exc instanceof Error ? exc.message : String(exc)}`
22659
22827
  ];
22660
22828
  }
22661
- if (!isObject7(state)) {
22829
+ if (!isObject8(state)) {
22662
22830
  return ["Checkpoint root must be a JSON object."];
22663
22831
  }
22664
22832
  const stateMap = state;
@@ -22683,7 +22851,7 @@ function validateOrchestratorStateText(text, options = {}) {
22683
22851
  if (receipts !== void 0 && receipts !== null) {
22684
22852
  if (Array.isArray(receipts)) {
22685
22853
  errors.push(...validateListDelegationReceipts(receipts));
22686
- } else if (isObject7(receipts)) {
22854
+ } else if (isObject8(receipts)) {
22687
22855
  errors.push(...validateNamespacedDelegationReceipts(receipts));
22688
22856
  } else {
22689
22857
  errors.push(
@@ -27041,6 +27209,13 @@ function copyTemplate(featureType, templateDir, targetDir, fs9) {
27041
27209
  }
27042
27210
  }
27043
27211
  }
27212
+ } else if (featureType === "epic") {
27213
+ for (const name of ["epic.md", "epic-status.md"]) {
27214
+ const src = joinPosix13(templateDir, name);
27215
+ if (fs9.exists(src)) {
27216
+ fs9.copyFile(src, joinPosix13(targetDir, name));
27217
+ }
27218
+ }
27044
27219
  } else {
27045
27220
  fs9.copyTree(templateDir, targetDir);
27046
27221
  }
@@ -27238,9 +27413,9 @@ function updateFeatureDocs(featureType, featureName, targetDir, issueField, owne
27238
27413
  );
27239
27414
  filesToOpen.push(spec, plan);
27240
27415
  } else if (featureType === "epic") {
27241
- const initiative = joinPosix13(targetDir, "initiative.md");
27416
+ const epic = joinPosix13(targetDir, "epic.md");
27242
27417
  applyHeaderAndSections(
27243
- initiative,
27418
+ epic,
27244
27419
  featureName,
27245
27420
  issueField,
27246
27421
  ownerField,
@@ -27251,7 +27426,7 @@ function updateFeatureDocs(featureType, featureName, targetDir, issueField, owne
27251
27426
  fs9,
27252
27427
  []
27253
27428
  );
27254
- filesToOpen.push(initiative);
27429
+ filesToOpen.push(epic);
27255
27430
  } else if (featureType === "bug") {
27256
27431
  const spec = joinPosix13(targetDir, "spec.md");
27257
27432
  const plan = planPath ?? joinPosix13(targetDir, "plan.md");
@@ -27418,15 +27593,18 @@ function createActiveFolder(options) {
27418
27593
  if (!normalizedIssueNumber) {
27419
27594
  normalizedIssueNumber = parseIssueNumber(potentialContent);
27420
27595
  }
27421
- const folderSlug = buildFolderSlug(
27422
- resolvedFeatureName,
27423
- potentialFile,
27424
- normalizedIssueNumber
27425
- );
27426
- const targetDir = joinPosix13(
27427
- workspacePath,
27428
- `docs/features/active/${folderSlug}`
27429
- );
27596
+ let targetDir;
27597
+ if (featureType === "epic") {
27598
+ const epicSlug = buildFolderSlug(resolvedFeatureName, null, null);
27599
+ targetDir = joinPosix13(workspacePath, `docs/features/epics/${epicSlug}`);
27600
+ } else {
27601
+ const folderSlug = buildFolderSlug(
27602
+ resolvedFeatureName,
27603
+ potentialFile,
27604
+ normalizedIssueNumber
27605
+ );
27606
+ targetDir = joinPosix13(workspacePath, `docs/features/active/${folderSlug}`);
27607
+ }
27430
27608
  if (filesystem.exists(targetDir) && !force) {
27431
27609
  throw new Error(
27432
27610
  `Target exists: ${targetDir}. Re-run with --force to overwrite.`
@@ -27631,6 +27809,299 @@ function newActiveFeatureFolderServiceCall(input) {
27631
27809
  };
27632
27810
  }
27633
27811
 
27812
+ // ../../extensions/drm-copilot/src/lib/subagent-tree/tree-assembler.ts
27813
+ var ROOT_KEY = "__root__";
27814
+ function assembleTree(scanned) {
27815
+ const transcriptsByKey = /* @__PURE__ */ new Map();
27816
+ transcriptsByKey.set(ROOT_KEY, scanned.root);
27817
+ for (const subagent of scanned.subagents) {
27818
+ transcriptsByKey.set(subagent.meta.agentId, subagent.transcript);
27819
+ }
27820
+ const matchedChildrenByParentKey = /* @__PURE__ */ new Map();
27821
+ const orphans = [];
27822
+ for (const subagent of scanned.subagents) {
27823
+ const parentKey = findParentKey(subagent.meta.toolUseId, transcriptsByKey);
27824
+ if (parentKey === void 0) {
27825
+ orphans.push(subagent);
27826
+ continue;
27827
+ }
27828
+ const siblings = matchedChildrenByParentKey.get(parentKey) ?? [];
27829
+ siblings.push(subagent);
27830
+ matchedChildrenByParentKey.set(parentKey, siblings);
27831
+ }
27832
+ orphans.sort(compareByAgentId);
27833
+ return buildNode({
27834
+ key: ROOT_KEY,
27835
+ agentType: "root",
27836
+ description: "",
27837
+ depth: 0,
27838
+ models: scanned.root.models,
27839
+ transcriptsByKey,
27840
+ matchedChildrenByParentKey,
27841
+ orphans
27842
+ });
27843
+ }
27844
+ function findParentKey(toolUseId, transcriptsByKey) {
27845
+ for (const [key, transcript] of transcriptsByKey) {
27846
+ if (transcript.agentToolUseIds.includes(toolUseId)) {
27847
+ return key;
27848
+ }
27849
+ }
27850
+ return void 0;
27851
+ }
27852
+ function compareByAgentId(a, b) {
27853
+ if (a.meta.agentId < b.meta.agentId) {
27854
+ return -1;
27855
+ }
27856
+ if (a.meta.agentId > b.meta.agentId) {
27857
+ return 1;
27858
+ }
27859
+ return 0;
27860
+ }
27861
+ function sortBySpawnIndex(children, parentTranscript) {
27862
+ return [...children].sort((a, b) => {
27863
+ const indexA = parentTranscript.agentToolUseIds.indexOf(a.meta.toolUseId);
27864
+ const indexB = parentTranscript.agentToolUseIds.indexOf(b.meta.toolUseId);
27865
+ if (indexA !== indexB) {
27866
+ return indexA - indexB;
27867
+ }
27868
+ return compareByAgentId(a, b);
27869
+ });
27870
+ }
27871
+ function buildNode(input) {
27872
+ const {
27873
+ key,
27874
+ agentType,
27875
+ description,
27876
+ depth,
27877
+ models,
27878
+ transcriptsByKey,
27879
+ matchedChildrenByParentKey,
27880
+ orphans
27881
+ } = input;
27882
+ const transcript = transcriptsByKey.get(key);
27883
+ const matchedChildren = matchedChildrenByParentKey.get(key) ?? [];
27884
+ const orderedMatched = transcript ? sortBySpawnIndex(matchedChildren, transcript) : matchedChildren;
27885
+ const isRoot = key === ROOT_KEY;
27886
+ const orderedChildren = isRoot ? [...orderedMatched, ...orphans] : orderedMatched;
27887
+ const children = orderedChildren.map(
27888
+ (subagent) => buildNode({
27889
+ key: subagent.meta.agentId,
27890
+ agentType: subagent.meta.agentType,
27891
+ description: subagent.meta.description,
27892
+ depth: subagent.meta.spawnDepth,
27893
+ models: subagent.transcript.models,
27894
+ transcriptsByKey,
27895
+ matchedChildrenByParentKey,
27896
+ orphans
27897
+ })
27898
+ );
27899
+ return {
27900
+ agentType,
27901
+ description,
27902
+ depth,
27903
+ models: [...models].sort(),
27904
+ children
27905
+ };
27906
+ }
27907
+
27908
+ // ../../extensions/drm-copilot/src/lib/subagent-tree/transcript-parser.ts
27909
+ function parseTranscriptLines(lines) {
27910
+ const models = [];
27911
+ const seenModels = /* @__PURE__ */ new Set();
27912
+ const agentToolUseIds = [];
27913
+ for (const line of lines) {
27914
+ const trimmed = line.trim();
27915
+ if (trimmed.length === 0) {
27916
+ continue;
27917
+ }
27918
+ const parsed = tryParseJson(trimmed);
27919
+ if (!isRecord2(parsed)) {
27920
+ continue;
27921
+ }
27922
+ const message = parsed["message"];
27923
+ if (!isRecord2(message)) {
27924
+ continue;
27925
+ }
27926
+ recordModel(message["model"], models, seenModels);
27927
+ collectAgentToolUseIds(message["content"], agentToolUseIds);
27928
+ }
27929
+ return { models, agentToolUseIds };
27930
+ }
27931
+ function tryParseJson(text) {
27932
+ try {
27933
+ return JSON.parse(text);
27934
+ } catch {
27935
+ return void 0;
27936
+ }
27937
+ }
27938
+ function isRecord2(value) {
27939
+ return typeof value === "object" && value !== null && !Array.isArray(value);
27940
+ }
27941
+ function recordModel(model, models, seenModels) {
27942
+ if (typeof model === "string" && model.length > 0 && !seenModels.has(model)) {
27943
+ seenModels.add(model);
27944
+ models.push(model);
27945
+ }
27946
+ }
27947
+ function collectAgentToolUseIds(content, agentToolUseIds) {
27948
+ if (!Array.isArray(content)) {
27949
+ return;
27950
+ }
27951
+ for (const block of content) {
27952
+ if (!isRecord2(block)) {
27953
+ continue;
27954
+ }
27955
+ if (block["type"] === "tool_use" && block["name"] === "Agent" && typeof block["id"] === "string") {
27956
+ agentToolUseIds.push(block["id"]);
27957
+ }
27958
+ }
27959
+ }
27960
+
27961
+ // ../../extensions/drm-copilot/src/lib/subagent-tree/transcript-scanner.ts
27962
+ var META_SUFFIX = ".meta.json";
27963
+ var TRANSCRIPT_SUFFIX = ".jsonl";
27964
+ var META_FILENAME_PATTERN = /agent-([^/\\]+)\.meta\.json$/;
27965
+ function scanTranscripts(rootSessionPath, fileSystem) {
27966
+ if (!rootSessionPath.endsWith(TRANSCRIPT_SUFFIX)) {
27967
+ throw new Error(
27968
+ `scanTranscripts: rootSessionPath must end in "${TRANSCRIPT_SUFFIX}", got: ${rootSessionPath}`
27969
+ );
27970
+ }
27971
+ const root = readTranscript(rootSessionPath, fileSystem);
27972
+ const subagentsDir = `${rootSessionPath.slice(0, -TRANSCRIPT_SUFFIX.length)}/subagents`;
27973
+ const metaPaths = fileSystem.glob(subagentsDir, "agent-*.meta.json");
27974
+ const subagents = metaPaths.map((metaPath) => readSubagent(metaPath, fileSystem)).filter((subagent) => subagent !== void 0);
27975
+ return { root, subagents };
27976
+ }
27977
+ function readTranscript(path11, fileSystem) {
27978
+ const content = fileSystem.readTextFile(path11);
27979
+ return parseTranscriptLines(content.split(/\r?\n/));
27980
+ }
27981
+ function readSubagent(metaPath, fileSystem) {
27982
+ const filenameMatch = META_FILENAME_PATTERN.exec(metaPath);
27983
+ const agentId = filenameMatch?.[1];
27984
+ if (agentId === void 0) {
27985
+ return void 0;
27986
+ }
27987
+ const metaContent = fileSystem.readTextFile(metaPath);
27988
+ const meta2 = parseSubagentMeta(agentId, metaContent);
27989
+ if (!meta2) {
27990
+ return void 0;
27991
+ }
27992
+ const transcriptPath = metaPath.slice(0, -META_SUFFIX.length) + TRANSCRIPT_SUFFIX;
27993
+ const transcript = readTranscript(transcriptPath, fileSystem);
27994
+ return { meta: meta2, transcript };
27995
+ }
27996
+ function parseSubagentMeta(agentId, content) {
27997
+ let parsed;
27998
+ try {
27999
+ parsed = JSON.parse(content);
28000
+ } catch {
28001
+ return void 0;
28002
+ }
28003
+ if (typeof parsed !== "object" || parsed === null) {
28004
+ return void 0;
28005
+ }
28006
+ const record2 = parsed;
28007
+ const agentType = record2["agentType"];
28008
+ const description = record2["description"];
28009
+ const toolUseId = record2["toolUseId"];
28010
+ const spawnDepth = record2["spawnDepth"];
28011
+ if (typeof agentType !== "string" || typeof description !== "string" || typeof toolUseId !== "string" || typeof spawnDepth !== "number") {
28012
+ return void 0;
28013
+ }
28014
+ const worktreePath = record2["worktreePath"];
28015
+ const worktreeBranch = record2["worktreeBranch"];
28016
+ return {
28017
+ agentId,
28018
+ agentType,
28019
+ description,
28020
+ toolUseId,
28021
+ spawnDepth,
28022
+ ...typeof worktreePath === "string" ? { worktreePath } : {},
28023
+ ...typeof worktreeBranch === "string" ? { worktreeBranch } : {}
28024
+ };
28025
+ }
28026
+
28027
+ // ../../extensions/drm-copilot/src/lib/subagent-tree/tree-formatter.ts
28028
+ function formatTree(node) {
28029
+ return renderLines(node).join("\n");
28030
+ }
28031
+ function renderLines(node) {
28032
+ const indent = " ".repeat(node.depth);
28033
+ const sortedModels = [...node.models].sort();
28034
+ const line = `${indent}${node.agentType} \xB7 [${sortedModels.join(",")}] \xB7 ${node.depth} \xB7 ${node.description}`;
28035
+ const childLines = node.children.flatMap((child) => renderLines(child));
28036
+ return [line, ...childLines];
28037
+ }
28038
+
28039
+ // ../../extensions/drm-copilot/src/lib/subagent-tree/index.ts
28040
+ function buildSubagentTree(rootSessionPath, deps) {
28041
+ const scanned = scanTranscripts(rootSessionPath, deps.fileSystem);
28042
+ return assembleTree(scanned);
28043
+ }
28044
+
28045
+ // ../../extensions/drm-copilot/src/lib/subagent-tree/workspace-encoding.ts
28046
+ var WORKTREE_INFIX = "-wt-";
28047
+ function encodeWorkspacePath(workspacePath) {
28048
+ return workspacePath.replace(/[\\/:]/g, "-");
28049
+ }
28050
+ function matchEncodedDirectories(directoryNames, encodedWorkspaceName) {
28051
+ const target = encodedWorkspaceName.toLowerCase();
28052
+ const worktreePrefix = `${target}${WORKTREE_INFIX}`;
28053
+ return directoryNames.filter((directoryName) => {
28054
+ const lowerDirectoryName = directoryName.toLowerCase();
28055
+ return lowerDirectoryName === target || lowerDirectoryName.startsWith(worktreePrefix);
28056
+ });
28057
+ }
28058
+
28059
+ // ../../extensions/drm-copilot/src/lib/subagent-tree/session-transcript-resolver.ts
28060
+ var SESSION_ID_PATTERN = /^[0-9A-Za-z-]{8,64}$/;
28061
+ var SESSION_ID_RULE = "^[0-9A-Za-z-]{8,64}$ (8-64 characters of digits, ASCII letters, or hyphen)";
28062
+ function resolveSessionTranscriptPath(sessionId, workspaceRoot, claudeProjectsRoot, fileSystem) {
28063
+ if (!SESSION_ID_PATTERN.test(sessionId)) {
28064
+ throw new Error(
28065
+ `Invalid session id '${sessionId}': must match ${SESSION_ID_RULE}.`
28066
+ );
28067
+ }
28068
+ const encodedWorkspaceName = encodeWorkspacePath(workspaceRoot);
28069
+ const matchingDirectories = matchEncodedDirectories(
28070
+ fileSystem.listDirectory(claudeProjectsRoot),
28071
+ encodedWorkspaceName
28072
+ );
28073
+ for (const directoryName of matchingDirectories) {
28074
+ const transcriptPath = `${claudeProjectsRoot}/${directoryName}/${sessionId}.jsonl`;
28075
+ if (fileSystem.isFile(transcriptPath)) {
28076
+ return transcriptPath;
28077
+ }
28078
+ }
28079
+ const searched = matchingDirectories.length === 0 ? "(no directories matched the encoded workspace path)" : matchingDirectories.map((directoryName) => `${claudeProjectsRoot}/${directoryName}`).join(", ");
28080
+ throw new Error(
28081
+ `No transcript found for session id '${sessionId}' under ${claudeProjectsRoot}. Searched: ${searched}.`
28082
+ );
28083
+ }
28084
+
28085
+ // ../../extensions/drm-copilot/src/repo-automation-service-subagent-tree.ts
28086
+ function renderSubagentTreeServiceCall(input, env = process.env) {
28087
+ const claudeProjectsRoot = getClaudeProjectsRoot(env);
28088
+ const transcriptPath = resolveSessionTranscriptPath(
28089
+ input.sessionId,
28090
+ input.workspaceRoot,
28091
+ claudeProjectsRoot,
28092
+ input.fileSystem
28093
+ );
28094
+ const renderedTree = formatTree(
28095
+ buildSubagentTree(transcriptPath, { fileSystem: input.fileSystem })
28096
+ );
28097
+ return {
28098
+ tool: "render_subagent_tree",
28099
+ workspaceRoot: input.workspaceRoot,
28100
+ summary: `Rendered subagent tree for session ${input.sessionId} (${transcriptPath}).`,
28101
+ renderedTree
28102
+ };
28103
+ }
28104
+
27634
28105
  // ../../extensions/drm-copilot/src/repo-automation-service.ts
27635
28106
  var DefaultRepoAutomationService = class {
27636
28107
  extensionRoot;
@@ -27800,23 +28271,14 @@ var DefaultRepoAutomationService = class {
27800
28271
  buildValidateOrchestrationServiceCallInput(this.fileSystem, input)
27801
28272
  );
27802
28273
  }
27803
- async executeScript(options) {
27804
- const execution = await executeBundledScriptFromExtensionRoot(this.output, {
27805
- runtimeKind: options.runtimeKind,
27806
- bundledRelativePath: options.bundledRelativePath,
27807
- commandId: options.invocationId,
27808
- args: options.args,
27809
- extensionRoot: this.extensionRoot,
27810
- workspaceRoot: options.workspaceRoot
28274
+ async renderSubagentTree(input) {
28275
+ return renderSubagentTreeServiceCall({
28276
+ ...input,
28277
+ fileSystem: this.fileSystem
27811
28278
  });
27812
- const parsedArtifactPath = options.stdoutArtifactPattern === void 0 ? void 0 : parseFirstArtifactPath(execution, options.stdoutArtifactPattern);
27813
- const artifacts = options.artifactPaths ?? (parsedArtifactPath === void 0 ? void 0 : [parsedArtifactPath]);
27814
- return {
27815
- tool: options.tool,
27816
- workspaceRoot: options.workspaceRoot,
27817
- summary: options.summary,
27818
- ...artifacts === void 0 ? {} : { artifacts }
27819
- };
28279
+ }
28280
+ async executeScript(options) {
28281
+ return executeScriptServiceCall(this.output, this.extensionRoot, options);
27820
28282
  }
27821
28283
  };
27822
28284
  function createRepoAutomationService(options) {