@danmoisan/drm-copilot-mcp 1.0.24 → 1.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/mcp-server.js +1045 -214
- package/package.json +1 -1
- package/resources/claude-customizations/.claude/agents/feature-review.md +5 -3
- package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +11 -4
- package/resources/claude-customizations/.claude/agents/parallel-planner.md +5 -2
- package/resources/claude-customizations/.claude/hooks/enforce-discovery-artifact-gate.ps1 +28 -8
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +109 -5
- package/resources/claude-customizations/.claude/hooks/enforce-mermaid-validation.ps1 +390 -0
- package/resources/claude-customizations/.claude/hooks/validate-discovery-artifact-gate.ps1 +28 -8
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +117 -46
- package/resources/claude-customizations/.claude/lib/bash/parallel-manifest-validate.sh +115 -3
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadius.psm1 +105 -2
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusConfig.psm1 +32 -52
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusExtraction.psm1 +107 -99
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusNormalization.psm1 +295 -0
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusValidation.psm1 +9 -3
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexDeployment.psm1 +312 -0
- package/resources/claude-customizations/.claude/lib/codex-routing/CodexTopology.psm1 +392 -0
- package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryValidation.psm1 +500 -0
- package/resources/claude-customizations/.claude/lib/mermaid/MermaidGrammar.psm1 +491 -0
- package/resources/claude-customizations/.claude/lib/mermaid/MermaidLineScanner.psm1 +488 -0
- package/resources/claude-customizations/.claude/lib/mermaid/MermaidMarkdownFences.psm1 +298 -0
- package/resources/claude-customizations/.claude/lib/mermaid/MermaidValidation.psm1 +496 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorState.psm1 +58 -67
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCheckpointValue.psm1 +383 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCodexModelReceipts.psm1 +297 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCodexTopologyReceipts.psm1 +298 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCompletion.psm1 +232 -43
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateCompletionChecks.psm1 +416 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateModelReceipts.psm1 +366 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateReceipts.psm1 +408 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRoutingContract.psm1 +428 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRoutingMatrix.psm1 +377 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateUnconditional.psm1 +166 -0
- package/resources/claude-customizations/.claude/rules/general-unit-test.md +1 -1
- package/resources/claude-customizations/.claude/rules/mermaid.md +142 -0
- package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +88 -3
- package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +116 -0
- package/resources/claude-customizations/.claude/rules/powershell.md +1 -1
- package/resources/claude-customizations/.claude/rules/quality-tiers.md +3 -3
- package/resources/claude-customizations/.claude/settings.json +5 -0
- package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +15 -0
- package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
- package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +6 -0
- package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +4 -4
- package/resources/claude-customizations/.claude/skills/mermaid-diagram/SKILL.md +184 -0
- package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/c4.md +50 -0
- package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/class.md +63 -0
- package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/er.md +56 -0
- package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/flowchart.md +68 -0
- package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/gantt.md +51 -0
- package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/other-types.md +82 -0
- package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/pie.md +32 -0
- package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/sequence.md +63 -0
- package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/state.md +49 -0
- package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +10 -5
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +116 -41
- package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +95 -13
- package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +7 -3
- package/resources/claude-customizations/.claude/skills/powershell-qa-gate/SKILL.md +1 -1
- package/resources/claude-customizations/config/blast-radius.json +9 -3
- package/resources/claude-customizations/pack-manifests/core.json +31 -1
- package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
- package/resources/codex-and-agents-customizations/.agents/skills/general-unit-test/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +3 -3
- package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
- package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +37 -1
package/out/mcp-server.js
CHANGED
|
@@ -6904,12 +6904,12 @@ var require_dist = __commonJS({
|
|
|
6904
6904
|
throw new Error(`Unknown format "${name}"`);
|
|
6905
6905
|
return f;
|
|
6906
6906
|
};
|
|
6907
|
-
function addFormats(ajv, list,
|
|
6907
|
+
function addFormats(ajv, list, fs10, exportName) {
|
|
6908
6908
|
var _a3;
|
|
6909
6909
|
var _b;
|
|
6910
6910
|
(_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
6911
6911
|
for (const f of list)
|
|
6912
|
-
ajv.addFormat(f,
|
|
6912
|
+
ajv.addFormat(f, fs10[f]);
|
|
6913
6913
|
}
|
|
6914
6914
|
module2.exports = exports2 = formatsPlugin;
|
|
6915
6915
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -6932,7 +6932,7 @@ __export(mcp_server_exports, {
|
|
|
6932
6932
|
main: () => main
|
|
6933
6933
|
});
|
|
6934
6934
|
module.exports = __toCommonJS(mcp_server_exports);
|
|
6935
|
-
var
|
|
6935
|
+
var fs9 = __toESM(require("node:fs"));
|
|
6936
6936
|
var path10 = __toESM(require("node:path"));
|
|
6937
6937
|
|
|
6938
6938
|
// node_modules/zod/v4/core/core.js
|
|
@@ -17260,7 +17260,8 @@ function toMcpToolResult(result) {
|
|
|
17260
17260
|
...result.assetId === void 0 ? {} : { asset_id: result.assetId },
|
|
17261
17261
|
...result.bundledSourcePath === void 0 ? {} : { bundled_source_path: result.bundledSourcePath },
|
|
17262
17262
|
...result.destinationPath === void 0 ? {} : { destination_path: result.destinationPath },
|
|
17263
|
-
...result.renderedTree === void 0 ? {} : { rendered_tree: result.renderedTree }
|
|
17263
|
+
...result.renderedTree === void 0 ? {} : { rendered_tree: result.renderedTree },
|
|
17264
|
+
...result.warnings === void 0 ? {} : { warnings: result.warnings }
|
|
17264
17265
|
};
|
|
17265
17266
|
}
|
|
17266
17267
|
function toFailureToolResult(tool, workspaceRoot, error2) {
|
|
@@ -17907,11 +17908,11 @@ function relativeToPosix(path11, root) {
|
|
|
17907
17908
|
}
|
|
17908
17909
|
return null;
|
|
17909
17910
|
}
|
|
17910
|
-
function enumerateSourceFiles(
|
|
17911
|
+
function enumerateSourceFiles(fs10, sourceRoot, rootFolders) {
|
|
17911
17912
|
const orderedFiles = [];
|
|
17912
17913
|
for (const root of rootFolders) {
|
|
17913
17914
|
const rootPath = joinPosix2(sourceRoot, root);
|
|
17914
|
-
const rootFiles =
|
|
17915
|
+
const rootFiles = fs10.listFiles(rootPath);
|
|
17915
17916
|
const sorted = [...rootFiles].sort((left, right) => {
|
|
17916
17917
|
const leftRel = relativeToPosix(left, rootPath) ?? left;
|
|
17917
17918
|
const rightRel = relativeToPosix(right, rootPath) ?? right;
|
|
@@ -17921,8 +17922,8 @@ function enumerateSourceFiles(fs9, sourceRoot, rootFolders) {
|
|
|
17921
17922
|
}
|
|
17922
17923
|
return orderedFiles;
|
|
17923
17924
|
}
|
|
17924
|
-
function validateDestination(destinationRoot, repoRoot,
|
|
17925
|
-
if (!
|
|
17925
|
+
function validateDestination(destinationRoot, repoRoot, fs10) {
|
|
17926
|
+
if (!fs10.isDir(destinationRoot)) {
|
|
17926
17927
|
throw new Error(
|
|
17927
17928
|
`Invalid destination: destination directory does not exist: ${destinationRoot}`
|
|
17928
17929
|
);
|
|
@@ -17985,22 +17986,22 @@ function stringifySorted(value, indent) {
|
|
|
17985
17986
|
};
|
|
17986
17987
|
return JSON.stringify(sortKeys(value), null, indent);
|
|
17987
17988
|
}
|
|
17988
|
-
function writeSummaryArtifact(
|
|
17989
|
+
function writeSummaryArtifact(fs10, summary, artifactRoot, artifactDirectory) {
|
|
17989
17990
|
const artifactPath = buildArtifactPath(
|
|
17990
17991
|
summary.startedAt,
|
|
17991
17992
|
artifactRoot,
|
|
17992
17993
|
artifactDirectory
|
|
17993
17994
|
);
|
|
17994
17995
|
const parent = artifactPath.slice(0, artifactPath.lastIndexOf("/"));
|
|
17995
|
-
|
|
17996
|
-
|
|
17996
|
+
fs10.ensureDir(parent);
|
|
17997
|
+
fs10.writeTextFile(artifactPath, renderPushDownSummary(summary));
|
|
17997
17998
|
return artifactPath;
|
|
17998
17999
|
}
|
|
17999
18000
|
function pushDownCustomizations(options) {
|
|
18000
18001
|
const {
|
|
18001
18002
|
repoRoot,
|
|
18002
18003
|
destinationRoot,
|
|
18003
|
-
fs:
|
|
18004
|
+
fs: fs10,
|
|
18004
18005
|
sourceRoot,
|
|
18005
18006
|
artifactRoot,
|
|
18006
18007
|
rootFolders,
|
|
@@ -18014,7 +18015,7 @@ function pushDownCustomizations(options) {
|
|
|
18014
18015
|
const effectiveArtifactDir = artifactDirectory ?? ARTIFACT_DIRECTORY;
|
|
18015
18016
|
const rewrite = rewriteReferences ?? rewriteTextReferences;
|
|
18016
18017
|
const now = clock ?? (() => /* @__PURE__ */ new Date());
|
|
18017
|
-
validateDestination(destinationRoot, repoRoot,
|
|
18018
|
+
validateDestination(destinationRoot, repoRoot, fs10);
|
|
18018
18019
|
const startedAt = now();
|
|
18019
18020
|
let createdCount = 0;
|
|
18020
18021
|
let overwrittenCount = 0;
|
|
@@ -18023,7 +18024,7 @@ function pushDownCustomizations(options) {
|
|
|
18023
18024
|
const unmatchedReferences = [];
|
|
18024
18025
|
const fileResults = [];
|
|
18025
18026
|
for (const sourcePath of enumerateSourceFiles(
|
|
18026
|
-
|
|
18027
|
+
fs10,
|
|
18027
18028
|
effectiveSource,
|
|
18028
18029
|
effectiveRoots
|
|
18029
18030
|
)) {
|
|
@@ -18032,7 +18033,7 @@ function pushDownCustomizations(options) {
|
|
|
18032
18033
|
continue;
|
|
18033
18034
|
}
|
|
18034
18035
|
const destinationPath = joinPosix2(destinationRoot, relativePath2);
|
|
18035
|
-
const destinationStatus =
|
|
18036
|
+
const destinationStatus = fs10.isFile(
|
|
18036
18037
|
destinationPath
|
|
18037
18038
|
) ? "overwritten" : "created";
|
|
18038
18039
|
if (destinationStatus === "created") {
|
|
@@ -18040,7 +18041,7 @@ function pushDownCustomizations(options) {
|
|
|
18040
18041
|
} else {
|
|
18041
18042
|
overwrittenCount += 1;
|
|
18042
18043
|
}
|
|
18043
|
-
const sourceText =
|
|
18044
|
+
const sourceText = fs10.readTextFile(sourcePath);
|
|
18044
18045
|
const [rewrittenText, rewrittenDelta, placeholderDelta, unmatched] = rewrite(sourceText);
|
|
18045
18046
|
rewrittenReferenceCount += rewrittenDelta;
|
|
18046
18047
|
placeholderRewriteCount += placeholderDelta;
|
|
@@ -18053,8 +18054,8 @@ function pushDownCustomizations(options) {
|
|
|
18053
18054
|
0,
|
|
18054
18055
|
destinationPath.lastIndexOf("/")
|
|
18055
18056
|
);
|
|
18056
|
-
|
|
18057
|
-
|
|
18057
|
+
fs10.ensureDir(destParent);
|
|
18058
|
+
fs10.writeTextFile(destinationPath, rewrittenText);
|
|
18058
18059
|
fileResults.push({
|
|
18059
18060
|
relativePath: relativePath2,
|
|
18060
18061
|
destinationStatus,
|
|
@@ -18078,7 +18079,7 @@ function pushDownCustomizations(options) {
|
|
|
18078
18079
|
artifactPath: ""
|
|
18079
18080
|
};
|
|
18080
18081
|
const artifactPath = writeSummaryArtifact(
|
|
18081
|
-
|
|
18082
|
+
fs10,
|
|
18082
18083
|
provisionalSummary,
|
|
18083
18084
|
effectiveArtifact,
|
|
18084
18085
|
effectiveArtifactDir
|
|
@@ -18142,7 +18143,7 @@ function joinPosix3(dir, name) {
|
|
|
18142
18143
|
const normalizedDir = dir.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
18143
18144
|
return normalizedDir === "" ? name : `${normalizedDir}/${name}`;
|
|
18144
18145
|
}
|
|
18145
|
-
function loadPackManifests(manifestDir, selectedPackNames,
|
|
18146
|
+
function loadPackManifests(manifestDir, selectedPackNames, fs10) {
|
|
18146
18147
|
const unknown2 = [...selectedPackNames].filter(
|
|
18147
18148
|
(name) => !MANIFEST_PACK_NAMES.has(name)
|
|
18148
18149
|
);
|
|
@@ -18154,14 +18155,14 @@ function loadPackManifests(manifestDir, selectedPackNames, fs9) {
|
|
|
18154
18155
|
const manifests = /* @__PURE__ */ new Map();
|
|
18155
18156
|
for (const name of [...namesToLoad].sort()) {
|
|
18156
18157
|
const manifestPath = joinPosix3(manifestDir, `${name}.json`);
|
|
18157
|
-
if (!
|
|
18158
|
+
if (!fs10.isFile(manifestPath)) {
|
|
18158
18159
|
throw new ManifestError(
|
|
18159
18160
|
`Codex pack manifest is missing for pack '${name}': ${manifestPath}`
|
|
18160
18161
|
);
|
|
18161
18162
|
}
|
|
18162
18163
|
manifests.set(
|
|
18163
18164
|
name,
|
|
18164
|
-
parseManifest(name, manifestPath,
|
|
18165
|
+
parseManifest(name, manifestPath, fs10.readTextFile(manifestPath))
|
|
18165
18166
|
);
|
|
18166
18167
|
}
|
|
18167
18168
|
return manifests;
|
|
@@ -18418,7 +18419,7 @@ var RoutingConfigFileSystem = class {
|
|
|
18418
18419
|
this.inner.ensureDir(path11);
|
|
18419
18420
|
}
|
|
18420
18421
|
};
|
|
18421
|
-
function resolvePublishedPaths(packs, csharpVariant, bundleRoot,
|
|
18422
|
+
function resolvePublishedPaths(packs, csharpVariant, bundleRoot, fs10) {
|
|
18422
18423
|
const manifestPacks = resolveManifestPackNames(packs ?? null, csharpVariant);
|
|
18423
18424
|
if (manifestPacks === null || manifestPacks.size === 0) {
|
|
18424
18425
|
return null;
|
|
@@ -18426,7 +18427,7 @@ function resolvePublishedPaths(packs, csharpVariant, bundleRoot, fs9) {
|
|
|
18426
18427
|
const manifests = loadPackManifests(
|
|
18427
18428
|
joinPosix4(bundleRoot, PACK_MANIFEST_SUBDIR),
|
|
18428
18429
|
manifestPacks,
|
|
18429
|
-
|
|
18430
|
+
fs10
|
|
18430
18431
|
);
|
|
18431
18432
|
const published = computePublishedPaths(manifestPacks, manifests) ?? /* @__PURE__ */ new Set();
|
|
18432
18433
|
assertSingleCsharpToolchain(published, manifestPacks);
|
|
@@ -18531,18 +18532,18 @@ function joinPosix5(dir, name) {
|
|
|
18531
18532
|
const normalizedDir = dir.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
18532
18533
|
return normalizedDir === "" ? name : `${normalizedDir}/${name}`;
|
|
18533
18534
|
}
|
|
18534
|
-
function loadPackManifests2(manifestDir, selectedPackNames,
|
|
18535
|
+
function loadPackManifests2(manifestDir, selectedPackNames, fs10) {
|
|
18535
18536
|
const namesToLoad = new Set(selectedPackNames);
|
|
18536
18537
|
namesToLoad.add(CORE_PACK_NAME2);
|
|
18537
18538
|
const manifests = /* @__PURE__ */ new Map();
|
|
18538
18539
|
for (const name of [...namesToLoad].sort()) {
|
|
18539
18540
|
const manifestPath = joinPosix5(manifestDir, `${name}.json`);
|
|
18540
|
-
if (!
|
|
18541
|
+
if (!fs10.isFile(manifestPath)) {
|
|
18541
18542
|
throw new ManifestError2(
|
|
18542
18543
|
`Pack manifest is missing for pack '${name}': ${manifestPath}`
|
|
18543
18544
|
);
|
|
18544
18545
|
}
|
|
18545
|
-
const rawText =
|
|
18546
|
+
const rawText = fs10.readTextFile(manifestPath);
|
|
18546
18547
|
manifests.set(name, parseManifest2(name, manifestPath, rawText));
|
|
18547
18548
|
}
|
|
18548
18549
|
return manifests;
|
|
@@ -18962,6 +18963,332 @@ var RoutingMergeFileSystem = class {
|
|
|
18962
18963
|
}
|
|
18963
18964
|
};
|
|
18964
18965
|
|
|
18966
|
+
// ../../extensions/drm-copilot/src/lib/push-down/claude-blast-radius-derive.ts
|
|
18967
|
+
var fs3 = __toESM(require("node:fs"));
|
|
18968
|
+
|
|
18969
|
+
// ../../extensions/drm-copilot/src/lib/push-down/claude-blast-radius-derive-core.ts
|
|
18970
|
+
var BLAST_RADIUS_RELATIVE_PATH = "config/blast-radius.json";
|
|
18971
|
+
var MANIFEST_FILENAMES = /* @__PURE__ */ new Set([
|
|
18972
|
+
"build.gradle",
|
|
18973
|
+
"build.gradle.kts",
|
|
18974
|
+
"Cargo.toml",
|
|
18975
|
+
"go.mod",
|
|
18976
|
+
"package.json",
|
|
18977
|
+
"pom.xml",
|
|
18978
|
+
"pyproject.toml",
|
|
18979
|
+
"setup.py"
|
|
18980
|
+
]);
|
|
18981
|
+
var MANIFEST_SUFFIXES = [
|
|
18982
|
+
".csproj",
|
|
18983
|
+
".fsproj",
|
|
18984
|
+
".vbproj",
|
|
18985
|
+
".sln",
|
|
18986
|
+
".slnx"
|
|
18987
|
+
];
|
|
18988
|
+
var EXCLUDED_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
18989
|
+
"__pycache__",
|
|
18990
|
+
"artifacts",
|
|
18991
|
+
"bin",
|
|
18992
|
+
"build",
|
|
18993
|
+
"coverage",
|
|
18994
|
+
"dist",
|
|
18995
|
+
"doc",
|
|
18996
|
+
"docs",
|
|
18997
|
+
"node_modules",
|
|
18998
|
+
"obj",
|
|
18999
|
+
"out",
|
|
19000
|
+
"target",
|
|
19001
|
+
"test",
|
|
19002
|
+
"tests",
|
|
19003
|
+
"venv"
|
|
19004
|
+
]);
|
|
19005
|
+
var SCAN_DEPTH_LIMIT = 3;
|
|
19006
|
+
var PAYLOAD_MODULES = {
|
|
19007
|
+
"claude-runtime": [".claude/**"],
|
|
19008
|
+
config: ["config/**"]
|
|
19009
|
+
};
|
|
19010
|
+
var FORBIDDEN_GLOBS = [
|
|
19011
|
+
"**",
|
|
19012
|
+
"docs/**",
|
|
19013
|
+
"tests/**"
|
|
19014
|
+
];
|
|
19015
|
+
var CARRIED_KEYS = [
|
|
19016
|
+
"version",
|
|
19017
|
+
"shared_surfaces",
|
|
19018
|
+
"shared_surface_globs",
|
|
19019
|
+
"over_breadth_fraction",
|
|
19020
|
+
"mandate_reads"
|
|
19021
|
+
];
|
|
19022
|
+
var BlastRadiusDeriveError = class extends Error {
|
|
19023
|
+
/** Destination-relative path of the document that failed to parse. */
|
|
19024
|
+
path;
|
|
19025
|
+
/**
|
|
19026
|
+
* @param path Path named in the message.
|
|
19027
|
+
* @param detail Parser detail appended to the message.
|
|
19028
|
+
*/
|
|
19029
|
+
constructor(path11, detail) {
|
|
19030
|
+
super(
|
|
19031
|
+
`Bundled blast-radius document is not valid JSON and was not written: ${path11} (${detail})`
|
|
19032
|
+
);
|
|
19033
|
+
this.name = "BlastRadiusDeriveError";
|
|
19034
|
+
this.path = path11;
|
|
19035
|
+
}
|
|
19036
|
+
};
|
|
19037
|
+
var BlastRadiusGuardError = class extends Error {
|
|
19038
|
+
/** The forbidden glob that tripped the guard. */
|
|
19039
|
+
glob;
|
|
19040
|
+
/** Name of the module that would have carried the forbidden glob. */
|
|
19041
|
+
moduleName;
|
|
19042
|
+
/**
|
|
19043
|
+
* @param moduleName Module the forbidden glob was assigned to.
|
|
19044
|
+
* @param glob The forbidden glob.
|
|
19045
|
+
*/
|
|
19046
|
+
constructor(moduleName, glob) {
|
|
19047
|
+
super(
|
|
19048
|
+
`Derived blast-radius module ${moduleName} would emit the forbidden glob ${glob}; the derivation was aborted before writing.`
|
|
19049
|
+
);
|
|
19050
|
+
this.name = "BlastRadiusGuardError";
|
|
19051
|
+
this.glob = glob;
|
|
19052
|
+
this.moduleName = moduleName;
|
|
19053
|
+
}
|
|
19054
|
+
};
|
|
19055
|
+
function compareOrdinal(left, right) {
|
|
19056
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
19057
|
+
}
|
|
19058
|
+
function isExcludedDirectoryName(name) {
|
|
19059
|
+
return name.startsWith(".") || EXCLUDED_DIR_NAMES.has(name);
|
|
19060
|
+
}
|
|
19061
|
+
function isManifestFileName(fileName) {
|
|
19062
|
+
if (MANIFEST_FILENAMES.has(fileName)) {
|
|
19063
|
+
return true;
|
|
19064
|
+
}
|
|
19065
|
+
return MANIFEST_SUFFIXES.some((suffix2) => fileName.endsWith(suffix2));
|
|
19066
|
+
}
|
|
19067
|
+
function classifyProjectDirectories(observations) {
|
|
19068
|
+
const projectPaths = [];
|
|
19069
|
+
for (const observation of observations) {
|
|
19070
|
+
if (observation.relativePath === "") {
|
|
19071
|
+
continue;
|
|
19072
|
+
}
|
|
19073
|
+
if (observation.fileNames.some(isManifestFileName)) {
|
|
19074
|
+
projectPaths.push(observation.relativePath);
|
|
19075
|
+
}
|
|
19076
|
+
}
|
|
19077
|
+
return projectPaths.sort(compareOrdinal);
|
|
19078
|
+
}
|
|
19079
|
+
function pruneAncestors(paths) {
|
|
19080
|
+
return paths.filter(
|
|
19081
|
+
(candidate) => !paths.some(
|
|
19082
|
+
(other) => other !== candidate && other.startsWith(`${candidate}/`)
|
|
19083
|
+
)
|
|
19084
|
+
);
|
|
19085
|
+
}
|
|
19086
|
+
function topLevelDirectories(observations) {
|
|
19087
|
+
const names = [];
|
|
19088
|
+
for (const observation of observations) {
|
|
19089
|
+
const relativePath2 = observation.relativePath;
|
|
19090
|
+
if (relativePath2 !== "" && !relativePath2.includes("/")) {
|
|
19091
|
+
names.push(relativePath2);
|
|
19092
|
+
}
|
|
19093
|
+
}
|
|
19094
|
+
return names.sort(compareOrdinal);
|
|
19095
|
+
}
|
|
19096
|
+
function assembleModules(derivedPaths) {
|
|
19097
|
+
const combined = /* @__PURE__ */ new Map();
|
|
19098
|
+
for (const path11 of derivedPaths) {
|
|
19099
|
+
combined.set(path11, [`${path11}/**`]);
|
|
19100
|
+
}
|
|
19101
|
+
for (const [name, globs] of Object.entries(PAYLOAD_MODULES)) {
|
|
19102
|
+
combined.set(name, [...globs]);
|
|
19103
|
+
}
|
|
19104
|
+
const modules = {};
|
|
19105
|
+
for (const name of [...combined.keys()].sort(compareOrdinal)) {
|
|
19106
|
+
const globs = combined.get(name);
|
|
19107
|
+
if (globs !== void 0) {
|
|
19108
|
+
modules[name] = globs;
|
|
19109
|
+
}
|
|
19110
|
+
}
|
|
19111
|
+
return modules;
|
|
19112
|
+
}
|
|
19113
|
+
function assertNoForbiddenGlob(modules) {
|
|
19114
|
+
for (const [name, globs] of Object.entries(modules)) {
|
|
19115
|
+
for (const glob of globs) {
|
|
19116
|
+
if (FORBIDDEN_GLOBS.includes(glob)) {
|
|
19117
|
+
throw new BlastRadiusGuardError(name, glob);
|
|
19118
|
+
}
|
|
19119
|
+
}
|
|
19120
|
+
}
|
|
19121
|
+
}
|
|
19122
|
+
function parseSourceDocument(text) {
|
|
19123
|
+
let parsed;
|
|
19124
|
+
try {
|
|
19125
|
+
parsed = JSON.parse(text);
|
|
19126
|
+
} catch (error2) {
|
|
19127
|
+
const detail = error2 instanceof Error ? error2.message : String(error2);
|
|
19128
|
+
throw new BlastRadiusDeriveError(BLAST_RADIUS_RELATIVE_PATH, detail);
|
|
19129
|
+
}
|
|
19130
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
19131
|
+
throw new BlastRadiusDeriveError(
|
|
19132
|
+
BLAST_RADIUS_RELATIVE_PATH,
|
|
19133
|
+
"document root is not a JSON object"
|
|
19134
|
+
);
|
|
19135
|
+
}
|
|
19136
|
+
return parsed;
|
|
19137
|
+
}
|
|
19138
|
+
function deriveDestinationModuleMap(observations, sourceDocumentText) {
|
|
19139
|
+
const source = parseSourceDocument(sourceDocumentText);
|
|
19140
|
+
const projectPaths = pruneAncestors(classifyProjectDirectories(observations));
|
|
19141
|
+
const derivedPaths = projectPaths.length > 0 ? projectPaths : topLevelDirectories(observations);
|
|
19142
|
+
const modules = assembleModules(derivedPaths);
|
|
19143
|
+
assertNoForbiddenGlob(modules);
|
|
19144
|
+
const document = {
|
|
19145
|
+
version: source[CARRIED_KEYS[0]],
|
|
19146
|
+
shared_surfaces: source[CARRIED_KEYS[1]],
|
|
19147
|
+
shared_surface_globs: source[CARRIED_KEYS[2]],
|
|
19148
|
+
mandate_reads: source[CARRIED_KEYS[4]],
|
|
19149
|
+
modules,
|
|
19150
|
+
over_breadth_fraction: source[CARRIED_KEYS[3]]
|
|
19151
|
+
};
|
|
19152
|
+
return `${JSON.stringify(document, null, 2)}
|
|
19153
|
+
`;
|
|
19154
|
+
}
|
|
19155
|
+
|
|
19156
|
+
// ../../extensions/drm-copilot/src/lib/push-down/claude-blast-radius-derive.ts
|
|
19157
|
+
function normalizePosix5(value) {
|
|
19158
|
+
return value.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
19159
|
+
}
|
|
19160
|
+
function relativeToPosix5(path11, root) {
|
|
19161
|
+
const normalizedPath = normalizePosix5(path11);
|
|
19162
|
+
const normalizedRoot = normalizePosix5(root);
|
|
19163
|
+
if (normalizedPath === normalizedRoot) {
|
|
19164
|
+
return "";
|
|
19165
|
+
}
|
|
19166
|
+
const prefix = `${normalizedRoot}/`;
|
|
19167
|
+
return normalizedPath.startsWith(prefix) ? normalizedPath.slice(prefix.length) : null;
|
|
19168
|
+
}
|
|
19169
|
+
var realDirectoryLister = (root) => {
|
|
19170
|
+
let entries;
|
|
19171
|
+
try {
|
|
19172
|
+
entries = fs3.readdirSync(root, { withFileTypes: true });
|
|
19173
|
+
} catch {
|
|
19174
|
+
return [];
|
|
19175
|
+
}
|
|
19176
|
+
return entries.map((entry) => ({ name: entry.name, isDir: entry.isDirectory() })).sort(
|
|
19177
|
+
(left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0
|
|
19178
|
+
);
|
|
19179
|
+
};
|
|
19180
|
+
function listTolerantly(lister, path11) {
|
|
19181
|
+
try {
|
|
19182
|
+
return lister(path11);
|
|
19183
|
+
} catch {
|
|
19184
|
+
return [];
|
|
19185
|
+
}
|
|
19186
|
+
}
|
|
19187
|
+
function collectDestinationObservations(destinationRoot, lister) {
|
|
19188
|
+
const root = normalizePosix5(destinationRoot);
|
|
19189
|
+
const observations = [];
|
|
19190
|
+
let queue = [
|
|
19191
|
+
{ path: root, relativePath: "" }
|
|
19192
|
+
];
|
|
19193
|
+
for (let depth = 1; depth <= SCAN_DEPTH_LIMIT && queue.length > 0; depth++) {
|
|
19194
|
+
const nextQueue = [];
|
|
19195
|
+
for (const current of queue) {
|
|
19196
|
+
const entries = listTolerantly(lister, current.path);
|
|
19197
|
+
const fileNames = [];
|
|
19198
|
+
for (const entry of entries) {
|
|
19199
|
+
if (!entry.isDir) {
|
|
19200
|
+
fileNames.push(entry.name);
|
|
19201
|
+
continue;
|
|
19202
|
+
}
|
|
19203
|
+
if (isExcludedDirectoryName(entry.name)) {
|
|
19204
|
+
continue;
|
|
19205
|
+
}
|
|
19206
|
+
nextQueue.push({
|
|
19207
|
+
path: `${current.path}/${entry.name}`,
|
|
19208
|
+
relativePath: current.relativePath === "" ? entry.name : `${current.relativePath}/${entry.name}`
|
|
19209
|
+
});
|
|
19210
|
+
}
|
|
19211
|
+
observations.push({
|
|
19212
|
+
relativePath: current.relativePath,
|
|
19213
|
+
fileNames
|
|
19214
|
+
});
|
|
19215
|
+
}
|
|
19216
|
+
queue = nextQueue;
|
|
19217
|
+
}
|
|
19218
|
+
return observations;
|
|
19219
|
+
}
|
|
19220
|
+
var BlastRadiusDeriveFileSystem = class {
|
|
19221
|
+
inner;
|
|
19222
|
+
destinationRoot;
|
|
19223
|
+
deriveRelativePath;
|
|
19224
|
+
lister;
|
|
19225
|
+
/**
|
|
19226
|
+
* @param inner The wrapped adapter performing real I/O.
|
|
19227
|
+
* @param destinationRoot Destination workspace root (POSIX path).
|
|
19228
|
+
* @param lister Shallow directory lister; defaults to the real filesystem.
|
|
19229
|
+
* @param deriveRelativePath Destination-relative path to derive; defaults to
|
|
19230
|
+
* `config/blast-radius.json`.
|
|
19231
|
+
*/
|
|
19232
|
+
constructor(inner, destinationRoot, lister = realDirectoryLister, deriveRelativePath = BLAST_RADIUS_RELATIVE_PATH) {
|
|
19233
|
+
this.inner = inner;
|
|
19234
|
+
this.destinationRoot = normalizePosix5(destinationRoot);
|
|
19235
|
+
this.lister = lister;
|
|
19236
|
+
this.deriveRelativePath = deriveRelativePath;
|
|
19237
|
+
}
|
|
19238
|
+
/** @inheritdoc */
|
|
19239
|
+
listFiles(root) {
|
|
19240
|
+
return this.inner.listFiles(root);
|
|
19241
|
+
}
|
|
19242
|
+
/** @inheritdoc */
|
|
19243
|
+
isDir(path11) {
|
|
19244
|
+
return this.inner.isDir(path11);
|
|
19245
|
+
}
|
|
19246
|
+
/** @inheritdoc */
|
|
19247
|
+
isFile(path11) {
|
|
19248
|
+
return this.inner.isFile(path11);
|
|
19249
|
+
}
|
|
19250
|
+
/** @inheritdoc */
|
|
19251
|
+
readTextFile(path11) {
|
|
19252
|
+
return this.inner.readTextFile(path11);
|
|
19253
|
+
}
|
|
19254
|
+
/** @inheritdoc */
|
|
19255
|
+
ensureDir(path11) {
|
|
19256
|
+
this.inner.ensureDir(path11);
|
|
19257
|
+
}
|
|
19258
|
+
/**
|
|
19259
|
+
* Write a file, deriving the one configured blast-radius path.
|
|
19260
|
+
*
|
|
19261
|
+
* @param path Absolute destination POSIX path.
|
|
19262
|
+
* @param content Bundled source content the engine wants to publish, used as
|
|
19263
|
+
* the derivation's base document rather than written verbatim.
|
|
19264
|
+
* @throws BlastRadiusDeriveError When the bundled document is not parseable.
|
|
19265
|
+
* @throws BlastRadiusGuardError When a forbidden glob would be emitted. Both
|
|
19266
|
+
* errors are raised before the inner write, so the destination bytes are
|
|
19267
|
+
* left untouched.
|
|
19268
|
+
*/
|
|
19269
|
+
writeTextFile(path11, content) {
|
|
19270
|
+
if (!this.isDeriveTarget(path11)) {
|
|
19271
|
+
this.inner.writeTextFile(path11, content);
|
|
19272
|
+
return;
|
|
19273
|
+
}
|
|
19274
|
+
const observations = collectDestinationObservations(
|
|
19275
|
+
this.destinationRoot,
|
|
19276
|
+
this.lister
|
|
19277
|
+
);
|
|
19278
|
+
const derived = deriveDestinationModuleMap(observations, content);
|
|
19279
|
+
this.inner.writeTextFile(path11, derived);
|
|
19280
|
+
}
|
|
19281
|
+
/**
|
|
19282
|
+
* Return whether a destination path is the configured derivation target.
|
|
19283
|
+
*
|
|
19284
|
+
* @param path Absolute destination POSIX path.
|
|
19285
|
+
* @returns True when the path resolves to the derive-target relative path.
|
|
19286
|
+
*/
|
|
19287
|
+
isDeriveTarget(path11) {
|
|
19288
|
+
return relativeToPosix5(path11, this.destinationRoot) === this.deriveRelativePath;
|
|
19289
|
+
}
|
|
19290
|
+
};
|
|
19291
|
+
|
|
18965
19292
|
// ../../extensions/drm-copilot/src/lib/push-down/claude-customizations.ts
|
|
18966
19293
|
var ARTIFACT_DIRECTORY4 = "artifacts/claude-customizations";
|
|
18967
19294
|
var ROOT_FOLDERS2 = [".claude", "config"];
|
|
@@ -18979,7 +19306,7 @@ function joinPosix7(root, relative2) {
|
|
|
18979
19306
|
const normalizedRelative = relative2.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
18980
19307
|
return normalizedRoot === "" ? normalizedRelative : `${normalizedRoot}/${normalizedRelative}`;
|
|
18981
19308
|
}
|
|
18982
|
-
function resolvePublishedPaths2(packs, bundleRoot,
|
|
19309
|
+
function resolvePublishedPaths2(packs, bundleRoot, fs10) {
|
|
18983
19310
|
if (packs === null || packs.size === 0) {
|
|
18984
19311
|
return null;
|
|
18985
19312
|
}
|
|
@@ -18987,7 +19314,7 @@ function resolvePublishedPaths2(packs, bundleRoot, fs9) {
|
|
|
18987
19314
|
const manifests = loadPackManifests2(
|
|
18988
19315
|
manifestDir,
|
|
18989
19316
|
packs,
|
|
18990
|
-
|
|
19317
|
+
fs10
|
|
18991
19318
|
);
|
|
18992
19319
|
const published = computePublishedPaths2(packs, manifests);
|
|
18993
19320
|
const effectivePublished = published ?? /* @__PURE__ */ new Set();
|
|
@@ -18998,29 +19325,35 @@ function pushDownCustomizations4(options) {
|
|
|
18998
19325
|
const {
|
|
18999
19326
|
repoRoot,
|
|
19000
19327
|
destinationRoot,
|
|
19001
|
-
fs:
|
|
19328
|
+
fs: fs10,
|
|
19002
19329
|
sourceRoot,
|
|
19003
19330
|
artifactRoot,
|
|
19004
19331
|
packs,
|
|
19005
19332
|
csharpVariant,
|
|
19006
19333
|
memoryMode,
|
|
19007
19334
|
bundleRoot,
|
|
19008
|
-
clock
|
|
19335
|
+
clock,
|
|
19336
|
+
listEntries
|
|
19009
19337
|
} = options;
|
|
19010
19338
|
const effectiveSource = sourceRoot ?? repoRoot;
|
|
19011
19339
|
const effectiveBundle = bundleRoot ?? joinPosix7(effectiveSource, BUNDLE_ROOT_RELATIVE_DIR);
|
|
19012
19340
|
const publishedPaths = resolvePublishedPaths2(
|
|
19013
19341
|
packs ?? null,
|
|
19014
19342
|
effectiveBundle,
|
|
19015
|
-
|
|
19343
|
+
fs10
|
|
19016
19344
|
);
|
|
19017
19345
|
const mergingFs = new RoutingMergeFileSystem(
|
|
19018
|
-
|
|
19346
|
+
fs10,
|
|
19019
19347
|
destinationRoot,
|
|
19020
19348
|
ROUTING_MERGE_RELATIVE_PATH
|
|
19021
19349
|
);
|
|
19022
|
-
const
|
|
19350
|
+
const derivingFs = listEntries === void 0 ? new BlastRadiusDeriveFileSystem(mergingFs, destinationRoot) : new BlastRadiusDeriveFileSystem(
|
|
19023
19351
|
mergingFs,
|
|
19352
|
+
destinationRoot,
|
|
19353
|
+
listEntries
|
|
19354
|
+
);
|
|
19355
|
+
const excludingFs = new ExcludingFileSystem(
|
|
19356
|
+
derivingFs,
|
|
19024
19357
|
repoRoot,
|
|
19025
19358
|
EXCLUDED_RELATIVE_PATHS,
|
|
19026
19359
|
{
|
|
@@ -19178,7 +19511,7 @@ function runPushDownClaudeCustomizations(input, deps) {
|
|
|
19178
19511
|
var path7 = __toESM(require("node:path"));
|
|
19179
19512
|
|
|
19180
19513
|
// ../../extensions/drm-copilot/src/policy-audit-template-assets.ts
|
|
19181
|
-
var
|
|
19514
|
+
var fs4 = __toESM(require("node:fs"));
|
|
19182
19515
|
var path5 = __toESM(require("node:path"));
|
|
19183
19516
|
var POLICY_AUDIT_TEMPLATE_ASSET_METADATA = {
|
|
19184
19517
|
template: {
|
|
@@ -19222,8 +19555,8 @@ function copyBundledPolicyAuditTemplateAsset(bundledSourcePath, targetPath) {
|
|
|
19222
19555
|
if (normalizedTargetPath === bundledSourcePath) {
|
|
19223
19556
|
return normalizedTargetPath;
|
|
19224
19557
|
}
|
|
19225
|
-
|
|
19226
|
-
|
|
19558
|
+
fs4.mkdirSync(path5.dirname(normalizedTargetPath), { recursive: true });
|
|
19559
|
+
fs4.copyFileSync(bundledSourcePath, normalizedTargetPath);
|
|
19227
19560
|
return normalizedTargetPath;
|
|
19228
19561
|
}
|
|
19229
19562
|
|
|
@@ -19231,7 +19564,7 @@ function copyBundledPolicyAuditTemplateAsset(bundledSourcePath, targetPath) {
|
|
|
19231
19564
|
var path6 = __toESM(require("node:path"));
|
|
19232
19565
|
|
|
19233
19566
|
// ../../extensions/drm-copilot/src/lib/file-system.ts
|
|
19234
|
-
var
|
|
19567
|
+
var fs5 = __toESM(require("node:fs"));
|
|
19235
19568
|
var nodePath3 = __toESM(require("node:path"));
|
|
19236
19569
|
function toPosixPath2(value) {
|
|
19237
19570
|
return value.replace(/\\/g, "/");
|
|
@@ -19302,7 +19635,7 @@ var RealFileSystem = class {
|
|
|
19302
19635
|
const walk = (currentDir, relativePrefix) => {
|
|
19303
19636
|
let entries;
|
|
19304
19637
|
try {
|
|
19305
|
-
entries =
|
|
19638
|
+
entries = fs5.readdirSync(currentDir, { withFileTypes: true });
|
|
19306
19639
|
} catch {
|
|
19307
19640
|
return;
|
|
19308
19641
|
}
|
|
@@ -19325,7 +19658,7 @@ var RealFileSystem = class {
|
|
|
19325
19658
|
*/
|
|
19326
19659
|
isFile(path11) {
|
|
19327
19660
|
try {
|
|
19328
|
-
return
|
|
19661
|
+
return fs5.statSync(path11).isFile();
|
|
19329
19662
|
} catch {
|
|
19330
19663
|
return false;
|
|
19331
19664
|
}
|
|
@@ -19335,7 +19668,7 @@ var RealFileSystem = class {
|
|
|
19335
19668
|
* @returns True when `path` exists; false on any access error.
|
|
19336
19669
|
*/
|
|
19337
19670
|
exists(path11) {
|
|
19338
|
-
return
|
|
19671
|
+
return fs5.existsSync(path11);
|
|
19339
19672
|
}
|
|
19340
19673
|
/**
|
|
19341
19674
|
* @param path Path to test.
|
|
@@ -19343,7 +19676,7 @@ var RealFileSystem = class {
|
|
|
19343
19676
|
*/
|
|
19344
19677
|
isDirectory(path11) {
|
|
19345
19678
|
try {
|
|
19346
|
-
return
|
|
19679
|
+
return fs5.statSync(path11).isDirectory();
|
|
19347
19680
|
} catch {
|
|
19348
19681
|
return false;
|
|
19349
19682
|
}
|
|
@@ -19355,7 +19688,7 @@ var RealFileSystem = class {
|
|
|
19355
19688
|
*/
|
|
19356
19689
|
listDirectory(path11) {
|
|
19357
19690
|
try {
|
|
19358
|
-
return
|
|
19691
|
+
return fs5.readdirSync(path11).sort((left, right) => left.localeCompare(right));
|
|
19359
19692
|
} catch {
|
|
19360
19693
|
return [];
|
|
19361
19694
|
}
|
|
@@ -19365,14 +19698,14 @@ var RealFileSystem = class {
|
|
|
19365
19698
|
* @returns The file content decoded as UTF-8.
|
|
19366
19699
|
*/
|
|
19367
19700
|
readTextFile(path11) {
|
|
19368
|
-
return
|
|
19701
|
+
return fs5.readFileSync(path11, "utf8");
|
|
19369
19702
|
}
|
|
19370
19703
|
/**
|
|
19371
19704
|
* @param path File to write.
|
|
19372
19705
|
* @param content Text content to write as UTF-8.
|
|
19373
19706
|
*/
|
|
19374
19707
|
writeTextFile(path11, content) {
|
|
19375
|
-
|
|
19708
|
+
fs5.writeFileSync(path11, content, "utf8");
|
|
19376
19709
|
}
|
|
19377
19710
|
/**
|
|
19378
19711
|
* Create the directory at `path`, including any missing parents.
|
|
@@ -19384,7 +19717,7 @@ var RealFileSystem = class {
|
|
|
19384
19717
|
* @param path Directory path to create.
|
|
19385
19718
|
*/
|
|
19386
19719
|
ensureDir(path11) {
|
|
19387
|
-
|
|
19720
|
+
fs5.mkdirSync(path11, { recursive: true });
|
|
19388
19721
|
}
|
|
19389
19722
|
};
|
|
19390
19723
|
|
|
@@ -19464,7 +19797,7 @@ function buildFallbackReason(issueContent) {
|
|
|
19464
19797
|
function resolveTemplateName(templateKind) {
|
|
19465
19798
|
return templateKind === "execute" ? "execute-hard-lock.prompt.md" : "resume-hard-lock.prompt.md";
|
|
19466
19799
|
}
|
|
19467
|
-
function resolveTemplatePath(templateName, workspaceRoot, templateRoot,
|
|
19800
|
+
function resolveTemplatePath(templateName, workspaceRoot, templateRoot, fs10) {
|
|
19468
19801
|
const candidates = [];
|
|
19469
19802
|
if (templateRoot !== null) {
|
|
19470
19803
|
candidates.push(joinPosix9(templateRoot, templateName));
|
|
@@ -19476,18 +19809,18 @@ function resolveTemplatePath(templateName, workspaceRoot, templateRoot, fs9) {
|
|
|
19476
19809
|
)
|
|
19477
19810
|
);
|
|
19478
19811
|
for (const candidate of candidates) {
|
|
19479
|
-
if (
|
|
19812
|
+
if (fs10.isFile(candidate)) {
|
|
19480
19813
|
return { path: candidate, checked: candidates };
|
|
19481
19814
|
}
|
|
19482
19815
|
}
|
|
19483
19816
|
return { path: null, checked: candidates };
|
|
19484
19817
|
}
|
|
19485
|
-
function resolveIssueFileForTarget(targetPath, workspaceRoot,
|
|
19818
|
+
function resolveIssueFileForTarget(targetPath, workspaceRoot, fs10) {
|
|
19486
19819
|
const normalizedRoot = toPosixPath2(workspaceRoot).replace(/\/+$/, "");
|
|
19487
19820
|
const relativeTarget = tryRelativeToWorkspace(targetPath, workspaceRoot);
|
|
19488
19821
|
const planDir = parentOf(relativeTarget);
|
|
19489
19822
|
const directIssue = joinPosix9(joinPosix9(normalizedRoot, planDir), "issue.md");
|
|
19490
|
-
if (
|
|
19823
|
+
if (fs10.isFile(directIssue)) {
|
|
19491
19824
|
return directIssue;
|
|
19492
19825
|
}
|
|
19493
19826
|
const planDirParts = splitParts(planDir);
|
|
@@ -19497,15 +19830,15 @@ function resolveIssueFileForTarget(targetPath, workspaceRoot, fs9) {
|
|
|
19497
19830
|
joinPosix9(normalizedRoot, parentOf(planDir)),
|
|
19498
19831
|
"issue.md"
|
|
19499
19832
|
);
|
|
19500
|
-
if (
|
|
19833
|
+
if (fs10.isFile(parentIssue)) {
|
|
19501
19834
|
return parentIssue;
|
|
19502
19835
|
}
|
|
19503
19836
|
}
|
|
19504
19837
|
return directIssue;
|
|
19505
19838
|
}
|
|
19506
|
-
function resolveWorkModeFromIssue(targetPath, workspaceRoot,
|
|
19507
|
-
const issuePath = resolveIssueFileForTarget(targetPath, workspaceRoot,
|
|
19508
|
-
if (!
|
|
19839
|
+
function resolveWorkModeFromIssue(targetPath, workspaceRoot, fs10) {
|
|
19840
|
+
const issuePath = resolveIssueFileForTarget(targetPath, workspaceRoot, fs10);
|
|
19841
|
+
if (!fs10.isFile(issuePath)) {
|
|
19509
19842
|
return {
|
|
19510
19843
|
mode: resolveSelectedWorkMode(null),
|
|
19511
19844
|
fallbackReason: buildFallbackReason(null)
|
|
@@ -19513,7 +19846,7 @@ function resolveWorkModeFromIssue(targetPath, workspaceRoot, fs9) {
|
|
|
19513
19846
|
}
|
|
19514
19847
|
let issueContent;
|
|
19515
19848
|
try {
|
|
19516
|
-
issueContent =
|
|
19849
|
+
issueContent = fs10.readTextFile(issuePath);
|
|
19517
19850
|
} catch {
|
|
19518
19851
|
return {
|
|
19519
19852
|
mode: resolveSelectedWorkMode(null),
|
|
@@ -19525,13 +19858,13 @@ function resolveWorkModeFromIssue(targetPath, workspaceRoot, fs9) {
|
|
|
19525
19858
|
fallbackReason: buildFallbackReason(issueContent)
|
|
19526
19859
|
};
|
|
19527
19860
|
}
|
|
19528
|
-
function resolveHardLockPrompt(templateContent, targetPath, workspaceRoot,
|
|
19861
|
+
function resolveHardLockPrompt(templateContent, targetPath, workspaceRoot, fs10) {
|
|
19529
19862
|
const relativeTarget = tryRelativeToWorkspace(targetPath, workspaceRoot);
|
|
19530
19863
|
const planPathValue = toPosixPath2(relativeTarget);
|
|
19531
19864
|
const { mode, fallbackReason } = resolveWorkModeFromIssue(
|
|
19532
19865
|
targetPath,
|
|
19533
19866
|
workspaceRoot,
|
|
19534
|
-
|
|
19867
|
+
fs10
|
|
19535
19868
|
);
|
|
19536
19869
|
let resolved = templateContent.split("${plan-path}").join(planPathValue);
|
|
19537
19870
|
resolved = resolved.split("${work-mode}").join(mode);
|
|
@@ -19789,18 +20122,18 @@ function isAllDigits(value) {
|
|
|
19789
20122
|
function resolveSpecPath(folderpath) {
|
|
19790
20123
|
return joinFolder(folderpath, "spec.md");
|
|
19791
20124
|
}
|
|
19792
|
-
function resolveUserStoryValue(folderpath, workspaceRoot,
|
|
20125
|
+
function resolveUserStoryValue(folderpath, workspaceRoot, fs10) {
|
|
19793
20126
|
const relativeStory = joinFolder(folderpath, "user-story.md");
|
|
19794
20127
|
const fullStory = joinFolder(toPosixPath2(workspaceRoot), relativeStory);
|
|
19795
|
-
if (
|
|
20128
|
+
if (fs10.isFile(fullStory)) {
|
|
19796
20129
|
return relativeStory;
|
|
19797
20130
|
}
|
|
19798
20131
|
return `${relativeStory} (missing)`;
|
|
19799
20132
|
}
|
|
19800
|
-
function resolveResearchValue(folderpath, workspaceRoot,
|
|
20133
|
+
function resolveResearchValue(folderpath, workspaceRoot, fs10) {
|
|
19801
20134
|
const relativeResearch = joinFolder(folderpath, "research.md");
|
|
19802
20135
|
const fullResearch = joinFolder(toPosixPath2(workspaceRoot), relativeResearch);
|
|
19803
|
-
if (
|
|
20136
|
+
if (fs10.isFile(fullResearch)) {
|
|
19804
20137
|
return relativeResearch;
|
|
19805
20138
|
}
|
|
19806
20139
|
return null;
|
|
@@ -19812,12 +20145,12 @@ function joinFolder(folder, leaf) {
|
|
|
19812
20145
|
}
|
|
19813
20146
|
return `${normalizedFolder}/${leaf}`;
|
|
19814
20147
|
}
|
|
19815
|
-
function resolveWorkModeFromIssue2(folderpath, workspaceRoot,
|
|
20148
|
+
function resolveWorkModeFromIssue2(folderpath, workspaceRoot, fs10) {
|
|
19816
20149
|
const issuePath = joinFolder(
|
|
19817
20150
|
joinFolder(toPosixPath2(workspaceRoot), folderpath),
|
|
19818
20151
|
"issue.md"
|
|
19819
20152
|
);
|
|
19820
|
-
if (!
|
|
20153
|
+
if (!fs10.isFile(issuePath)) {
|
|
19821
20154
|
return {
|
|
19822
20155
|
mode: resolveSelectedWorkMode(null),
|
|
19823
20156
|
fallbackReason: buildFallbackReason(null)
|
|
@@ -19825,7 +20158,7 @@ function resolveWorkModeFromIssue2(folderpath, workspaceRoot, fs9) {
|
|
|
19825
20158
|
}
|
|
19826
20159
|
let issueContent;
|
|
19827
20160
|
try {
|
|
19828
|
-
issueContent =
|
|
20161
|
+
issueContent = fs10.readTextFile(issuePath);
|
|
19829
20162
|
} catch {
|
|
19830
20163
|
return {
|
|
19831
20164
|
mode: resolveSelectedWorkMode(null),
|
|
@@ -19839,7 +20172,7 @@ function resolveWorkModeFromIssue2(folderpath, workspaceRoot, fs9) {
|
|
|
19839
20172
|
}
|
|
19840
20173
|
|
|
19841
20174
|
// ../../extensions/drm-copilot/src/lib/resolve/file-prompt-core.ts
|
|
19842
|
-
function resolvePrompt(templateContent, targetPath, workspaceRoot,
|
|
20175
|
+
function resolvePrompt(templateContent, targetPath, workspaceRoot, fs10) {
|
|
19843
20176
|
let content = stripFrontMatter(templateContent);
|
|
19844
20177
|
const relativeTarget = tryRelativeToWorkspace2(targetPath, workspaceRoot);
|
|
19845
20178
|
const fileValue = toPosixPath2(relativeTarget);
|
|
@@ -19851,19 +20184,19 @@ function resolvePrompt(templateContent, targetPath, workspaceRoot, fs9) {
|
|
|
19851
20184
|
folderpath,
|
|
19852
20185
|
name,
|
|
19853
20186
|
spec: resolveSpecPath(folderpath),
|
|
19854
|
-
"user-story": resolveUserStoryValue(folderpath, workspaceRoot,
|
|
20187
|
+
"user-story": resolveUserStoryValue(folderpath, workspaceRoot, fs10)
|
|
19855
20188
|
};
|
|
19856
20189
|
const { mode, fallbackReason } = resolveWorkModeFromIssue2(
|
|
19857
20190
|
folderpath,
|
|
19858
20191
|
workspaceRoot,
|
|
19859
|
-
|
|
20192
|
+
fs10
|
|
19860
20193
|
);
|
|
19861
20194
|
variables["work-mode"] = mode;
|
|
19862
20195
|
variables["fallback-reason"] = fallbackReason;
|
|
19863
20196
|
if (mode === "minor-audit") {
|
|
19864
20197
|
content = applyMinorAuditOverrides(content);
|
|
19865
20198
|
}
|
|
19866
|
-
const researchValue = resolveResearchValue(folderpath, workspaceRoot,
|
|
20199
|
+
const researchValue = resolveResearchValue(folderpath, workspaceRoot, fs10);
|
|
19867
20200
|
if (researchValue === null) {
|
|
19868
20201
|
content = removeLinesReferencingVariable(content, "research");
|
|
19869
20202
|
} else {
|
|
@@ -25518,9 +25851,9 @@ function validatePhaseCompleteness(state) {
|
|
|
25518
25851
|
(phase) => `Checkpoint completion validation failed: route ${routeId} is missing mandatory phase ${phase}.`
|
|
25519
25852
|
);
|
|
25520
25853
|
}
|
|
25521
|
-
function loadRoutingMatrix(
|
|
25854
|
+
function loadRoutingMatrix(fs10, root) {
|
|
25522
25855
|
const path11 = `${toPosixPath2(root).replace(/\/+$/, "")}/${ROUTING_MATRIX_RELATIVE_PATH}`;
|
|
25523
|
-
return JSON.parse(
|
|
25856
|
+
return JSON.parse(fs10.readTextFile(path11));
|
|
25524
25857
|
}
|
|
25525
25858
|
function stringList(value) {
|
|
25526
25859
|
if (!Array.isArray(value)) {
|
|
@@ -26516,6 +26849,417 @@ function validateParallelKickoffText(text) {
|
|
|
26516
26849
|
return parseParallelKickoff(text).errors;
|
|
26517
26850
|
}
|
|
26518
26851
|
|
|
26852
|
+
// ../../extensions/drm-copilot/src/lib/validate/plan-gate-commands.ts
|
|
26853
|
+
var SHELL_WHITESPACE = /* @__PURE__ */ new Set([" ", " ", "\r", "\n"]);
|
|
26854
|
+
var ESCAPE = "\\";
|
|
26855
|
+
var COV_FLAG = "--cov";
|
|
26856
|
+
var COV_FLAG_PREFIX = "--cov=";
|
|
26857
|
+
var GREP_EXECUTABLES = /* @__PURE__ */ new Set(["grep", "egrep", "fgrep", "rg"]);
|
|
26858
|
+
var EXECUTABLE_SCAN_LIMIT = 4;
|
|
26859
|
+
var PLAN_GATE_TASK_PATTERN = /^- \[(?<state>[ xX])\] \[P(?<phase>\d+)-T(?<task>\d+)\] (?<title>.+)$/;
|
|
26860
|
+
var PLAN_GATE_HEADING_PATTERN = /^#{1,6} /;
|
|
26861
|
+
var INLINE_SPAN_RE = /`([^`]+)`/g;
|
|
26862
|
+
var FENCE_RE = /^\s*```/;
|
|
26863
|
+
var MINIMUM_ARGV_LENGTH = 2;
|
|
26864
|
+
function splitShellWords(span) {
|
|
26865
|
+
const words2 = [];
|
|
26866
|
+
let token = null;
|
|
26867
|
+
let quote = null;
|
|
26868
|
+
let index = 0;
|
|
26869
|
+
while (index < span.length) {
|
|
26870
|
+
const char = span[index] ?? "";
|
|
26871
|
+
index += 1;
|
|
26872
|
+
if (quote === null) {
|
|
26873
|
+
if (SHELL_WHITESPACE.has(char)) {
|
|
26874
|
+
if (token !== null) {
|
|
26875
|
+
words2.push(token);
|
|
26876
|
+
token = null;
|
|
26877
|
+
}
|
|
26878
|
+
continue;
|
|
26879
|
+
}
|
|
26880
|
+
if (char === ESCAPE) {
|
|
26881
|
+
const next = span[index];
|
|
26882
|
+
if (next === void 0) {
|
|
26883
|
+
return null;
|
|
26884
|
+
}
|
|
26885
|
+
index += 1;
|
|
26886
|
+
token = (token ?? "") + next;
|
|
26887
|
+
continue;
|
|
26888
|
+
}
|
|
26889
|
+
if (char === '"' || char === "'") {
|
|
26890
|
+
quote = char;
|
|
26891
|
+
token = token ?? "";
|
|
26892
|
+
continue;
|
|
26893
|
+
}
|
|
26894
|
+
token = (token ?? "") + char;
|
|
26895
|
+
continue;
|
|
26896
|
+
}
|
|
26897
|
+
if (char === quote) {
|
|
26898
|
+
quote = null;
|
|
26899
|
+
continue;
|
|
26900
|
+
}
|
|
26901
|
+
if (quote === '"' && char === ESCAPE) {
|
|
26902
|
+
const next = span[index];
|
|
26903
|
+
if (next === void 0) {
|
|
26904
|
+
return null;
|
|
26905
|
+
}
|
|
26906
|
+
index += 1;
|
|
26907
|
+
if (next !== quote && next !== ESCAPE) {
|
|
26908
|
+
token = (token ?? "") + ESCAPE;
|
|
26909
|
+
}
|
|
26910
|
+
token = (token ?? "") + next;
|
|
26911
|
+
continue;
|
|
26912
|
+
}
|
|
26913
|
+
token = (token ?? "") + char;
|
|
26914
|
+
}
|
|
26915
|
+
if (quote !== null) {
|
|
26916
|
+
return null;
|
|
26917
|
+
}
|
|
26918
|
+
if (token !== null) {
|
|
26919
|
+
words2.push(token);
|
|
26920
|
+
}
|
|
26921
|
+
return words2;
|
|
26922
|
+
}
|
|
26923
|
+
function isCovFlagToken(token) {
|
|
26924
|
+
return token === COV_FLAG || token.startsWith(COV_FLAG_PREFIX);
|
|
26925
|
+
}
|
|
26926
|
+
function grepExecutableIndex(argv) {
|
|
26927
|
+
const limit = Math.min(argv.length, EXECUTABLE_SCAN_LIMIT);
|
|
26928
|
+
for (let index = 0; index < limit; index += 1) {
|
|
26929
|
+
const word = argv[index];
|
|
26930
|
+
if (word === void 0) {
|
|
26931
|
+
continue;
|
|
26932
|
+
}
|
|
26933
|
+
if (GREP_EXECUTABLES.has(word)) {
|
|
26934
|
+
return index;
|
|
26935
|
+
}
|
|
26936
|
+
if (word === "git" && argv[index + 1] === "grep") {
|
|
26937
|
+
return index + 1;
|
|
26938
|
+
}
|
|
26939
|
+
}
|
|
26940
|
+
return null;
|
|
26941
|
+
}
|
|
26942
|
+
function classifyKind(argv) {
|
|
26943
|
+
if (grepExecutableIndex(argv) !== null) {
|
|
26944
|
+
return "grep";
|
|
26945
|
+
}
|
|
26946
|
+
if (argv.some((word) => isCovFlagToken(word))) {
|
|
26947
|
+
return "pytest_cov";
|
|
26948
|
+
}
|
|
26949
|
+
return "other";
|
|
26950
|
+
}
|
|
26951
|
+
function splitLines2(text) {
|
|
26952
|
+
return text.split(/\r\n|\n|\r/);
|
|
26953
|
+
}
|
|
26954
|
+
function inlineSpans(line) {
|
|
26955
|
+
const spans = [];
|
|
26956
|
+
for (const match of line.matchAll(INLINE_SPAN_RE)) {
|
|
26957
|
+
const body = match[1];
|
|
26958
|
+
if (body !== void 0) {
|
|
26959
|
+
spans.push(body);
|
|
26960
|
+
}
|
|
26961
|
+
}
|
|
26962
|
+
return spans;
|
|
26963
|
+
}
|
|
26964
|
+
function appendCommand(commands, taskId, sourceLine, rawSpan) {
|
|
26965
|
+
const argv = splitShellWords(rawSpan);
|
|
26966
|
+
if (argv === null || argv.length < MINIMUM_ARGV_LENGTH) {
|
|
26967
|
+
return;
|
|
26968
|
+
}
|
|
26969
|
+
commands.push({
|
|
26970
|
+
taskId,
|
|
26971
|
+
sourceLine,
|
|
26972
|
+
rawSpan,
|
|
26973
|
+
argv,
|
|
26974
|
+
kind: classifyKind(argv)
|
|
26975
|
+
});
|
|
26976
|
+
}
|
|
26977
|
+
function extractPlanCommands(text) {
|
|
26978
|
+
const commands = [];
|
|
26979
|
+
let currentTask = null;
|
|
26980
|
+
let inFence = false;
|
|
26981
|
+
const lines = splitLines2(text);
|
|
26982
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
26983
|
+
const line = lines[index] ?? "";
|
|
26984
|
+
const lineNumber = index + 1;
|
|
26985
|
+
if (FENCE_RE.test(line)) {
|
|
26986
|
+
inFence = !inFence;
|
|
26987
|
+
continue;
|
|
26988
|
+
}
|
|
26989
|
+
if (inFence) {
|
|
26990
|
+
const fenced = line.trim();
|
|
26991
|
+
if (currentTask !== null && fenced !== "") {
|
|
26992
|
+
appendCommand(commands, currentTask, lineNumber, fenced);
|
|
26993
|
+
}
|
|
26994
|
+
continue;
|
|
26995
|
+
}
|
|
26996
|
+
if (PLAN_GATE_HEADING_PATTERN.test(line)) {
|
|
26997
|
+
currentTask = null;
|
|
26998
|
+
continue;
|
|
26999
|
+
}
|
|
27000
|
+
const taskMatch = PLAN_GATE_TASK_PATTERN.exec(line);
|
|
27001
|
+
if (taskMatch !== null) {
|
|
27002
|
+
const phase = taskMatch.groups?.["phase"] ?? "";
|
|
27003
|
+
const task = taskMatch.groups?.["task"] ?? "";
|
|
27004
|
+
currentTask = `P${phase}-T${task}`;
|
|
27005
|
+
}
|
|
27006
|
+
if (currentTask === null) {
|
|
27007
|
+
continue;
|
|
27008
|
+
}
|
|
27009
|
+
for (const span of inlineSpans(line)) {
|
|
27010
|
+
appendCommand(commands, currentTask, lineNumber, span);
|
|
27011
|
+
}
|
|
27012
|
+
}
|
|
27013
|
+
return commands;
|
|
27014
|
+
}
|
|
27015
|
+
|
|
27016
|
+
// ../../extensions/drm-copilot/src/lib/validate/plan-gate-rules.ts
|
|
27017
|
+
function emptyPlanGateReport() {
|
|
27018
|
+
return { blocking: [], warnings: [] };
|
|
27019
|
+
}
|
|
27020
|
+
var BLOCKING_CHANNEL = "blocking";
|
|
27021
|
+
var PLACEHOLDER_MARKERS = ["<", ">", "${", "$(", "%"];
|
|
27022
|
+
var PATH_SEPARATORS = ["/", "\\"];
|
|
27023
|
+
var PYTHON_SUFFIX = ".py";
|
|
27024
|
+
var PYTEST_NODE_SEPARATOR = "::";
|
|
27025
|
+
var REGEX_METACHARACTERS = /* @__PURE__ */ new Set([...".*[]^$\\(){}|+?"]);
|
|
27026
|
+
var FIXED_STRING_FLAG = "-F";
|
|
27027
|
+
var WINDOW_SIZE = 4;
|
|
27028
|
+
function isPlaceholder(value) {
|
|
27029
|
+
return PLACEHOLDER_MARKERS.some((marker) => value.includes(marker));
|
|
27030
|
+
}
|
|
27031
|
+
function dottedRemedy(value) {
|
|
27032
|
+
const stem2 = value.endsWith(PYTHON_SUFFIX) ? value.slice(0, value.length - PYTHON_SUFFIX.length) : value;
|
|
27033
|
+
return stem2.split("/").join(".").split("\\").join(".");
|
|
27034
|
+
}
|
|
27035
|
+
function covValues(command) {
|
|
27036
|
+
const values = [];
|
|
27037
|
+
const argv = command.argv;
|
|
27038
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
27039
|
+
const word = argv[index];
|
|
27040
|
+
if (word === void 0) {
|
|
27041
|
+
continue;
|
|
27042
|
+
}
|
|
27043
|
+
if (word === COV_FLAG) {
|
|
27044
|
+
const next = argv[index + 1];
|
|
27045
|
+
if (next !== void 0) {
|
|
27046
|
+
values.push({ value: next, spaceSeparated: true });
|
|
27047
|
+
}
|
|
27048
|
+
continue;
|
|
27049
|
+
}
|
|
27050
|
+
if (word.startsWith(COV_FLAG_PREFIX)) {
|
|
27051
|
+
values.push({
|
|
27052
|
+
value: word.slice(COV_FLAG_PREFIX.length),
|
|
27053
|
+
spaceSeparated: false
|
|
27054
|
+
});
|
|
27055
|
+
}
|
|
27056
|
+
}
|
|
27057
|
+
return values;
|
|
27058
|
+
}
|
|
27059
|
+
function evaluateCovValue(report, command, cov, context) {
|
|
27060
|
+
const task = command.taskId;
|
|
27061
|
+
if (cov.spaceSeparated) {
|
|
27062
|
+
report.warnings.push(
|
|
27063
|
+
`[${task}] --cov argument value \`${cov.value}\` is supplied space-separated; the ambiguous form can bind the following positional argument. Use the --cov=<module> form.`
|
|
27064
|
+
);
|
|
27065
|
+
}
|
|
27066
|
+
if (isPlaceholder(cov.value)) {
|
|
27067
|
+
return;
|
|
27068
|
+
}
|
|
27069
|
+
const truncated = cov.value.split(PYTEST_NODE_SEPARATOR)[0] ?? "";
|
|
27070
|
+
if (truncated.endsWith(PYTHON_SUFFIX)) {
|
|
27071
|
+
report.blocking.push(
|
|
27072
|
+
`[${task}] --cov argument \`${cov.value}\` names a filesystem path; coverage.py accepts only directories or importable names. Use --cov=${dottedRemedy(truncated)}.`
|
|
27073
|
+
);
|
|
27074
|
+
return;
|
|
27075
|
+
}
|
|
27076
|
+
if (!PATH_SEPARATORS.some((separator) => cov.value.includes(separator))) {
|
|
27077
|
+
return;
|
|
27078
|
+
}
|
|
27079
|
+
if (context === void 0) {
|
|
27080
|
+
return;
|
|
27081
|
+
}
|
|
27082
|
+
try {
|
|
27083
|
+
evaluateTrackedCovValue(report, task, cov, truncated, context);
|
|
27084
|
+
} catch {
|
|
27085
|
+
}
|
|
27086
|
+
}
|
|
27087
|
+
function evaluateTrackedCovValue(report, task, cov, truncated, context) {
|
|
27088
|
+
if (context.git.isTrackedFile(truncated + PYTHON_SUFFIX)) {
|
|
27089
|
+
report.blocking.push(
|
|
27090
|
+
`[${task}] --cov argument \`${cov.value}\` names a tracked module file path; coverage.py accepts only directories or importable names. Use --cov=${dottedRemedy(truncated)}.`
|
|
27091
|
+
);
|
|
27092
|
+
return;
|
|
27093
|
+
}
|
|
27094
|
+
if (context.git.isTrackedDirectory(truncated)) {
|
|
27095
|
+
return;
|
|
27096
|
+
}
|
|
27097
|
+
report.warnings.push(
|
|
27098
|
+
`[${task}] --cov argument \`${cov.value}\` contains a path separator but resolves to neither a tracked file nor a tracked directory; coverage may collect no data. Use the importable dotted form or a tracked directory.`
|
|
27099
|
+
);
|
|
27100
|
+
}
|
|
27101
|
+
function patternOperand(argv) {
|
|
27102
|
+
const executable = grepExecutableIndex(argv);
|
|
27103
|
+
if (executable === null) {
|
|
27104
|
+
return null;
|
|
27105
|
+
}
|
|
27106
|
+
for (let index = executable + 1; index < argv.length; index += 1) {
|
|
27107
|
+
const word = argv[index];
|
|
27108
|
+
if (word === void 0 || word.startsWith("-")) {
|
|
27109
|
+
continue;
|
|
27110
|
+
}
|
|
27111
|
+
return word;
|
|
27112
|
+
}
|
|
27113
|
+
return null;
|
|
27114
|
+
}
|
|
27115
|
+
function isCheckableLiteral(argv, pattern) {
|
|
27116
|
+
if (isPlaceholder(pattern)) {
|
|
27117
|
+
return false;
|
|
27118
|
+
}
|
|
27119
|
+
if (argv.includes(FIXED_STRING_FLAG)) {
|
|
27120
|
+
return true;
|
|
27121
|
+
}
|
|
27122
|
+
return ![...pattern].some((character) => REGEX_METACHARACTERS.has(character));
|
|
27123
|
+
}
|
|
27124
|
+
function normalizeWhitespace(value) {
|
|
27125
|
+
return value.split(/\s+/).filter((word) => word !== "").join(" ");
|
|
27126
|
+
}
|
|
27127
|
+
function planQuotesLiteral(text, literal2, excludeSpan) {
|
|
27128
|
+
const remainder = text.split(excludeSpan).join(" ");
|
|
27129
|
+
const needle = normalizeWhitespace(literal2);
|
|
27130
|
+
if (needle === "") {
|
|
27131
|
+
return false;
|
|
27132
|
+
}
|
|
27133
|
+
return normalizeWhitespace(remainder).includes(needle);
|
|
27134
|
+
}
|
|
27135
|
+
function windowJoin(lines, size = WINDOW_SIZE) {
|
|
27136
|
+
const dense = lines.filter((line) => line.trim() !== "").map((line) => normalizeWhitespace(line));
|
|
27137
|
+
const windows = [];
|
|
27138
|
+
for (let index = 0; index < dense.length; index += 1) {
|
|
27139
|
+
windows.push(dense.slice(index, index + size).join(" "));
|
|
27140
|
+
}
|
|
27141
|
+
return windows;
|
|
27142
|
+
}
|
|
27143
|
+
function hasCrossLinePresence(context, literal2) {
|
|
27144
|
+
const words2 = literal2.split(/\s+/).filter((word) => word !== "");
|
|
27145
|
+
if (words2.length < 2) {
|
|
27146
|
+
return false;
|
|
27147
|
+
}
|
|
27148
|
+
const needle = words2.join(" ");
|
|
27149
|
+
const firstWord = words2[0] ?? "";
|
|
27150
|
+
for (const path11 of context.git.filesContaining(firstWord)) {
|
|
27151
|
+
const lines = context.git.readTrackedText(path11).split(/\r\n|\n|\r/);
|
|
27152
|
+
if (lines.some((line) => normalizeWhitespace(line).includes(needle))) {
|
|
27153
|
+
continue;
|
|
27154
|
+
}
|
|
27155
|
+
if (windowJoin(lines).some((window2) => window2.includes(needle))) {
|
|
27156
|
+
return true;
|
|
27157
|
+
}
|
|
27158
|
+
}
|
|
27159
|
+
return false;
|
|
27160
|
+
}
|
|
27161
|
+
|
|
27162
|
+
// ../../extensions/drm-copilot/src/lib/validate/plan-gate-discrimination.ts
|
|
27163
|
+
var G5_SEVERITY = "warning";
|
|
27164
|
+
var CommandRunnerPlanGateRepository = class {
|
|
27165
|
+
constructor(workspaceRoot, runner) {
|
|
27166
|
+
this.workspaceRoot = workspaceRoot;
|
|
27167
|
+
this.runner = runner;
|
|
27168
|
+
}
|
|
27169
|
+
workspaceRoot;
|
|
27170
|
+
runner;
|
|
27171
|
+
/** Run one `git` invocation and return its exit code and trimmed stdout. */
|
|
27172
|
+
run(arguments_) {
|
|
27173
|
+
const result = this.runner.run(["git", ...arguments_], {
|
|
27174
|
+
cwd: this.workspaceRoot,
|
|
27175
|
+
allowError: true
|
|
27176
|
+
});
|
|
27177
|
+
return { code: result.code, stdout: result.stdout.trim() };
|
|
27178
|
+
}
|
|
27179
|
+
/** Return tracked paths carrying the literal on a single line. */
|
|
27180
|
+
filesContaining(literal2) {
|
|
27181
|
+
const result = this.run(["grep", "-F", "-l", "--", literal2]);
|
|
27182
|
+
if (result.code !== 0 || result.stdout === "") {
|
|
27183
|
+
return [];
|
|
27184
|
+
}
|
|
27185
|
+
return result.stdout.split(/\r\n|\n|\r/).map((line) => line.trim()).filter((line) => line !== "");
|
|
27186
|
+
}
|
|
27187
|
+
/** Return whether `git ls-files` lists the path itself. */
|
|
27188
|
+
isTrackedFile(path11) {
|
|
27189
|
+
const normalized = path11.split("\\").join("/");
|
|
27190
|
+
const result = this.run(["ls-files", "--", normalized]);
|
|
27191
|
+
if (result.code !== 0 || result.stdout === "") {
|
|
27192
|
+
return false;
|
|
27193
|
+
}
|
|
27194
|
+
return result.stdout.split(/\r\n|\n|\r/).some((line) => line.trim() === normalized);
|
|
27195
|
+
}
|
|
27196
|
+
/** Return whether entries exist beneath the path but none equals it. */
|
|
27197
|
+
isTrackedDirectory(path11) {
|
|
27198
|
+
const normalized = path11.split("\\").join("/").replace(/\/+$/, "");
|
|
27199
|
+
const result = this.run(["ls-files", "--", normalized]);
|
|
27200
|
+
if (result.code !== 0 || result.stdout === "") {
|
|
27201
|
+
return false;
|
|
27202
|
+
}
|
|
27203
|
+
const listed = result.stdout.split(/\r\n|\n|\r/).map((line) => line.trim()).filter((line) => line !== "");
|
|
27204
|
+
return listed.length > 0 && listed.every((entry) => entry !== normalized);
|
|
27205
|
+
}
|
|
27206
|
+
/** Return the committed text of the path at `HEAD`, or an empty string. */
|
|
27207
|
+
readTrackedText(path11) {
|
|
27208
|
+
const normalized = path11.split("\\").join("/");
|
|
27209
|
+
const result = this.run(["show", `HEAD:${normalized}`]);
|
|
27210
|
+
return result.code === 0 ? result.stdout : "";
|
|
27211
|
+
}
|
|
27212
|
+
};
|
|
27213
|
+
function evaluateLiteral(report, text, command, context) {
|
|
27214
|
+
const pattern = patternOperand(command.argv);
|
|
27215
|
+
if (pattern === null || !isCheckableLiteral(command.argv, pattern)) {
|
|
27216
|
+
return;
|
|
27217
|
+
}
|
|
27218
|
+
if (context.git.filesContaining(pattern).length > 0) {
|
|
27219
|
+
return;
|
|
27220
|
+
}
|
|
27221
|
+
if (planQuotesLiteral(text, pattern, command.rawSpan)) {
|
|
27222
|
+
return;
|
|
27223
|
+
}
|
|
27224
|
+
if (hasCrossLinePresence(context, pattern)) {
|
|
27225
|
+
report.warnings.push(
|
|
27226
|
+
`[${command.taskId}] search literal \`${pattern}\` is present only across adjacent lines of a tracked file and matches no single line; a line-oriented search returns zero matches. Search a shorter single-line token.`
|
|
27227
|
+
);
|
|
27228
|
+
return;
|
|
27229
|
+
}
|
|
27230
|
+
const finding = `[${command.taskId}] search literal \`${pattern}\` is absent from the tracked tree and is not quoted in the plan; the search returns zero matches whatever the executor does. Quote the exact literal the task will create, or assert a literal that exists.`;
|
|
27231
|
+
const channel = G5_SEVERITY === BLOCKING_CHANNEL ? report.blocking : report.warnings;
|
|
27232
|
+
channel.push(finding);
|
|
27233
|
+
}
|
|
27234
|
+
function evaluateLiteralRules(report, text, commands, context) {
|
|
27235
|
+
const literalFindings = emptyPlanGateReport();
|
|
27236
|
+
try {
|
|
27237
|
+
for (const command of commands) {
|
|
27238
|
+
if (command.kind !== "grep") {
|
|
27239
|
+
continue;
|
|
27240
|
+
}
|
|
27241
|
+
evaluateLiteral(literalFindings, text, command, context);
|
|
27242
|
+
}
|
|
27243
|
+
} catch {
|
|
27244
|
+
return;
|
|
27245
|
+
}
|
|
27246
|
+
report.blocking.push(...literalFindings.blocking);
|
|
27247
|
+
report.warnings.push(...literalFindings.warnings);
|
|
27248
|
+
}
|
|
27249
|
+
function evaluatePlanGates(text, context) {
|
|
27250
|
+
const report = emptyPlanGateReport();
|
|
27251
|
+
const commands = extractPlanCommands(text);
|
|
27252
|
+
for (const command of commands) {
|
|
27253
|
+
for (const cov of covValues(command)) {
|
|
27254
|
+
evaluateCovValue(report, command, cov, context);
|
|
27255
|
+
}
|
|
27256
|
+
}
|
|
27257
|
+
if (context !== void 0) {
|
|
27258
|
+
evaluateLiteralRules(report, text, commands, context);
|
|
27259
|
+
}
|
|
27260
|
+
return report;
|
|
27261
|
+
}
|
|
27262
|
+
|
|
26519
27263
|
// ../../extensions/drm-copilot/src/lib/validate/parallel-state-shared.ts
|
|
26520
27264
|
function words(text) {
|
|
26521
27265
|
return text.split(" ");
|
|
@@ -27301,7 +28045,7 @@ function validateReceiptArrays(state, context) {
|
|
|
27301
28045
|
var CONTEXT = "Parallel checkpoint";
|
|
27302
28046
|
var EXPECTED_ROUTE_ID2 = "parallel";
|
|
27303
28047
|
var MIN_CONCURRENCY = 1;
|
|
27304
|
-
var MAX_CONCURRENCY =
|
|
28048
|
+
var MAX_CONCURRENCY = 32;
|
|
27305
28049
|
var REQUIRED_KEYS4 = [
|
|
27306
28050
|
"objective",
|
|
27307
28051
|
"completed_steps",
|
|
@@ -27451,7 +28195,7 @@ function validateParallelOrchestratorStateText(text, options = {}) {
|
|
|
27451
28195
|
// ../../extensions/drm-copilot/src/lib/validate/parallel-planner-state-core.ts
|
|
27452
28196
|
var CONTEXT2 = "Parallel planner checkpoint";
|
|
27453
28197
|
var MIN_CONCURRENCY2 = 1;
|
|
27454
|
-
var MAX_CONCURRENCY2 =
|
|
28198
|
+
var MAX_CONCURRENCY2 = 32;
|
|
27455
28199
|
var REQUIRED_KEYS5 = [
|
|
27456
28200
|
"objective",
|
|
27457
28201
|
"parallel_slug",
|
|
@@ -27690,7 +28434,7 @@ var POLICY_AUDIT_REQUIRED_CHECKLIST_LABELS = [
|
|
|
27690
28434
|
"Per-language comparison summary:"
|
|
27691
28435
|
];
|
|
27692
28436
|
var POLICY_AUDIT_COMPARISON_HEADING = "### 1.2.1 Per-Language Coverage Comparison";
|
|
27693
|
-
var
|
|
28437
|
+
var PLACEHOLDER_MARKERS2 = [
|
|
27694
28438
|
"[n]",
|
|
27695
28439
|
"[path",
|
|
27696
28440
|
"[artifact",
|
|
@@ -27716,7 +28460,7 @@ function isNaValue(value) {
|
|
|
27716
28460
|
}
|
|
27717
28461
|
function hasPlaceholderMarker(value) {
|
|
27718
28462
|
const lowered = value.toLowerCase();
|
|
27719
|
-
return
|
|
28463
|
+
return PLACEHOLDER_MARKERS2.some((marker) => lowered.includes(marker));
|
|
27720
28464
|
}
|
|
27721
28465
|
function reportsMissingTemplateResolverSuccess(text) {
|
|
27722
28466
|
const lowered = text.toLowerCase();
|
|
@@ -28023,10 +28767,28 @@ function validatePlanText(text) {
|
|
|
28023
28767
|
}
|
|
28024
28768
|
return errors;
|
|
28025
28769
|
}
|
|
28026
|
-
function
|
|
28770
|
+
function buildPlanGateContext(input) {
|
|
28771
|
+
if (input.fs === void 0 || input.root === void 0 || input.artifactPath === void 0 || input.runner === void 0) {
|
|
28772
|
+
return void 0;
|
|
28773
|
+
}
|
|
28774
|
+
return {
|
|
28775
|
+
workspaceRoot: input.root,
|
|
28776
|
+
fileSystem: input.fs,
|
|
28777
|
+
git: new CommandRunnerPlanGateRepository(input.root, input.runner)
|
|
28778
|
+
};
|
|
28779
|
+
}
|
|
28780
|
+
function validateArtifactWithWarnings(input) {
|
|
28781
|
+
if (input.artifactType === "plan") {
|
|
28782
|
+
const report = evaluatePlanGates(input.text, buildPlanGateContext(input));
|
|
28783
|
+
return {
|
|
28784
|
+
errors: [...validatePlanText(input.text), ...report.blocking],
|
|
28785
|
+
warnings: report.warnings
|
|
28786
|
+
};
|
|
28787
|
+
}
|
|
28788
|
+
return { errors: dispatchValidatorErrors(input), warnings: [] };
|
|
28789
|
+
}
|
|
28790
|
+
function dispatchValidatorErrors(input) {
|
|
28027
28791
|
switch (input.artifactType) {
|
|
28028
|
-
case "plan":
|
|
28029
|
-
return validatePlanText(input.text);
|
|
28030
28792
|
case "policy-audit":
|
|
28031
28793
|
return validatePolicyAuditText(input.text);
|
|
28032
28794
|
case "code-review":
|
|
@@ -28089,12 +28851,13 @@ function validateArtifact(input) {
|
|
|
28089
28851
|
}
|
|
28090
28852
|
|
|
28091
28853
|
// ../../extensions/drm-copilot/src/lib/validate/validate-orchestration-service-call.ts
|
|
28854
|
+
var PLAN_GATE_WARNING_PREFIX = "PLAN GATE WARNING: ";
|
|
28092
28855
|
function validateOrchestrationServiceCall(input) {
|
|
28093
28856
|
const artifactFullPath = toPosixPath2(
|
|
28094
28857
|
path9.join(input.workspaceRoot, input.artifactPath)
|
|
28095
28858
|
);
|
|
28096
28859
|
const text = input.fileSystem.readTextFile(artifactFullPath);
|
|
28097
|
-
const errors =
|
|
28860
|
+
const { errors, warnings } = validateArtifactWithWarnings({
|
|
28098
28861
|
artifactType: input.artifactType,
|
|
28099
28862
|
text,
|
|
28100
28863
|
...input.requireComplete === void 0 ? {} : { requireComplete: input.requireComplete },
|
|
@@ -28108,15 +28871,17 @@ function validateOrchestrationServiceCall(input) {
|
|
|
28108
28871
|
root: input.workspaceRoot
|
|
28109
28872
|
});
|
|
28110
28873
|
if (errors.length > 0) {
|
|
28874
|
+
const warningBlock = warnings.length === 0 ? "" : "\n" + warnings.map((warning) => `${PLAN_GATE_WARNING_PREFIX}${warning}`).join("\n");
|
|
28111
28875
|
throw new Error(
|
|
28112
28876
|
`Validation failed for ${input.artifactType} artifact at '${input.artifactPath}':
|
|
28113
|
-
${errors.join("\n")}`
|
|
28877
|
+
${errors.join("\n")}${warningBlock}`
|
|
28114
28878
|
);
|
|
28115
28879
|
}
|
|
28116
28880
|
return {
|
|
28117
28881
|
tool: "validate_orchestration_artifacts",
|
|
28118
28882
|
workspaceRoot: input.workspaceRoot,
|
|
28119
|
-
summary: `Validated ${input.artifactType} artifact at '${input.artifactPath}'
|
|
28883
|
+
summary: `Validated ${input.artifactType} artifact at '${input.artifactPath}'.`,
|
|
28884
|
+
...warnings.length === 0 ? {} : { warnings }
|
|
28120
28885
|
};
|
|
28121
28886
|
}
|
|
28122
28887
|
|
|
@@ -28137,7 +28902,7 @@ function buildValidateOrchestrationServiceCallInput(fileSystem, input, runner) {
|
|
|
28137
28902
|
}
|
|
28138
28903
|
|
|
28139
28904
|
// ../../extensions/drm-copilot/src/lib/new-potential-bug-entry.ts
|
|
28140
|
-
var
|
|
28905
|
+
var fs6 = __toESM(require("node:fs"));
|
|
28141
28906
|
var nodePath4 = __toESM(require("node:path"));
|
|
28142
28907
|
var SHORT_NAME_PATTERN2 = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
28143
28908
|
var INSIDERS_SIGNAL_NAMES = [
|
|
@@ -28210,7 +28975,7 @@ function defaultWhichLookup(executable) {
|
|
|
28210
28975
|
directory,
|
|
28211
28976
|
process.platform === "win32" ? `${executable}${extension}` : executable
|
|
28212
28977
|
);
|
|
28213
|
-
if (
|
|
28978
|
+
if (fs6.existsSync(candidate)) {
|
|
28214
28979
|
return candidate;
|
|
28215
28980
|
}
|
|
28216
28981
|
}
|
|
@@ -28339,7 +29104,7 @@ function truncate(text, limit = 800) {
|
|
|
28339
29104
|
}
|
|
28340
29105
|
return rstrip3(text.slice(0, limit - 3)) + "...";
|
|
28341
29106
|
}
|
|
28342
|
-
function
|
|
29107
|
+
function splitLines3(value) {
|
|
28343
29108
|
if (value === "") {
|
|
28344
29109
|
return [];
|
|
28345
29110
|
}
|
|
@@ -28350,7 +29115,7 @@ function splitLines2(value) {
|
|
|
28350
29115
|
return lines;
|
|
28351
29116
|
}
|
|
28352
29117
|
function truncateLines(text, limit) {
|
|
28353
|
-
const lines =
|
|
29118
|
+
const lines = splitLines3(text);
|
|
28354
29119
|
if (lines.length <= limit) {
|
|
28355
29120
|
return text;
|
|
28356
29121
|
}
|
|
@@ -29114,7 +29879,7 @@ function convertNumstat(numstatText) {
|
|
|
29114
29879
|
let adds = 0;
|
|
29115
29880
|
let dels = 0;
|
|
29116
29881
|
const files = [];
|
|
29117
|
-
for (const rawLine of
|
|
29882
|
+
for (const rawLine of splitLines4(numstatText)) {
|
|
29118
29883
|
if (!rawLine.trim()) {
|
|
29119
29884
|
continue;
|
|
29120
29885
|
}
|
|
@@ -29177,7 +29942,7 @@ function summarizeConventionalCommits(subjects) {
|
|
|
29177
29942
|
}
|
|
29178
29943
|
counts.set("other", 0);
|
|
29179
29944
|
const typePattern = /^(feat|fix|refactor|perf|docs|test|chore|build|ci|style)(\(|!|:)/u;
|
|
29180
|
-
for (const rawLine of
|
|
29945
|
+
for (const rawLine of splitLines4(subjects)) {
|
|
29181
29946
|
const line = rawLine.trim();
|
|
29182
29947
|
if (!line) {
|
|
29183
29948
|
continue;
|
|
@@ -29232,7 +29997,7 @@ function buildIssuesToAutocloseSection(params) {
|
|
|
29232
29997
|
function extractChangedPaths(contextText) {
|
|
29233
29998
|
const paths = [];
|
|
29234
29999
|
let capture = false;
|
|
29235
|
-
for (const line of
|
|
30000
|
+
for (const line of splitLines4(contextText)) {
|
|
29236
30001
|
if (line.startsWith("===== Changed files")) {
|
|
29237
30002
|
capture = true;
|
|
29238
30003
|
continue;
|
|
@@ -29278,7 +30043,7 @@ function compareCodePoint2(left, right) {
|
|
|
29278
30043
|
}
|
|
29279
30044
|
return 0;
|
|
29280
30045
|
}
|
|
29281
|
-
function
|
|
30046
|
+
function splitLines4(value) {
|
|
29282
30047
|
if (value === "") {
|
|
29283
30048
|
return [];
|
|
29284
30049
|
}
|
|
@@ -29348,7 +30113,7 @@ function buildPrContext(options) {
|
|
|
29348
30113
|
const subjects = git.log("--pretty=%s", revRange);
|
|
29349
30114
|
const authors = git.log("--format=%an <%ae>", revRange);
|
|
29350
30115
|
const authorsList = sortedSet2(
|
|
29351
|
-
|
|
30116
|
+
splitLines5(authors).map((line) => line.trim()).filter((line) => line)
|
|
29352
30117
|
);
|
|
29353
30118
|
const nameStatus = git.diffRange(["--name-status", mergeBase, headSha]);
|
|
29354
30119
|
const numstat = git.diffRange(["--numstat", mergeBase, headSha]);
|
|
@@ -29356,7 +30121,7 @@ function buildPrContext(options) {
|
|
|
29356
30121
|
const stat = git.diffRange(["--stat", mergeBase, headSha]);
|
|
29357
30122
|
const [additions, deletions, files] = convertNumstat(numstat);
|
|
29358
30123
|
const extSummary = extensionSummary(files);
|
|
29359
|
-
const mergePrs = extractMergePrNumbers(
|
|
30124
|
+
const mergePrs = extractMergePrNumbers(splitLines5(oneline));
|
|
29360
30125
|
const issueCandidates = extractIssueReferences(
|
|
29361
30126
|
oneline + "\n" + subjects
|
|
29362
30127
|
).filter((ref) => !mergePrs.includes(ref));
|
|
@@ -29515,7 +30280,7 @@ function compareCodePoint3(left, right) {
|
|
|
29515
30280
|
}
|
|
29516
30281
|
return 0;
|
|
29517
30282
|
}
|
|
29518
|
-
function
|
|
30283
|
+
function splitLines5(value) {
|
|
29519
30284
|
if (value === "") {
|
|
29520
30285
|
return [];
|
|
29521
30286
|
}
|
|
@@ -29541,7 +30306,7 @@ function parseSection2(markdown, heading) {
|
|
|
29541
30306
|
}
|
|
29542
30307
|
function completedPlanTasks2(markdown, limit = 10) {
|
|
29543
30308
|
const tasks = [];
|
|
29544
|
-
for (const line of
|
|
30309
|
+
for (const line of splitLines3(markdown)) {
|
|
29545
30310
|
if (/\[x\]/iu.test(line)) {
|
|
29546
30311
|
const cleaned = line.replace(/^[-*]\s*\[[xX]\]\s*/u, "").trim();
|
|
29547
30312
|
tasks.push(cleaned);
|
|
@@ -29567,9 +30332,9 @@ function extractIssueReferences2(text) {
|
|
|
29567
30332
|
}
|
|
29568
30333
|
return ordered;
|
|
29569
30334
|
}
|
|
29570
|
-
function resolveFeatureDir2(
|
|
30335
|
+
function resolveFeatureDir2(fs10, baseDir, feature) {
|
|
29571
30336
|
const direct = `${baseDir}/${feature}`;
|
|
29572
|
-
if (
|
|
30337
|
+
if (fs10.exists(direct)) {
|
|
29573
30338
|
return direct;
|
|
29574
30339
|
}
|
|
29575
30340
|
const pattern = new RegExp(
|
|
@@ -29578,9 +30343,9 @@ function resolveFeatureDir2(fs9, baseDir, feature) {
|
|
|
29578
30343
|
);
|
|
29579
30344
|
const strongMatches = [];
|
|
29580
30345
|
const weakMatches = [];
|
|
29581
|
-
for (const name of
|
|
30346
|
+
for (const name of fs10.listDirectory(baseDir)) {
|
|
29582
30347
|
const candidate = `${baseDir}/${name}`;
|
|
29583
|
-
if (!
|
|
30348
|
+
if (!fs10.isDirectory(candidate)) {
|
|
29584
30349
|
continue;
|
|
29585
30350
|
}
|
|
29586
30351
|
if (pattern.test(name)) {
|
|
@@ -29597,11 +30362,11 @@ function resolveFeatureDir2(fs9, baseDir, feature) {
|
|
|
29597
30362
|
}
|
|
29598
30363
|
return null;
|
|
29599
30364
|
}
|
|
29600
|
-
function readText(
|
|
29601
|
-
return
|
|
30365
|
+
function readText(fs10, path11) {
|
|
30366
|
+
return fs10.exists(path11) ? fs10.readTextFile(path11) : "";
|
|
29602
30367
|
}
|
|
29603
|
-
function latestGlobPath(
|
|
29604
|
-
const matches = [...
|
|
30368
|
+
function latestGlobPath(fs10, directory, pattern) {
|
|
30369
|
+
const matches = [...fs10.glob(directory, pattern)].sort(compareCodePoint4);
|
|
29605
30370
|
return matches.length > 0 ? matches[matches.length - 1] : null;
|
|
29606
30371
|
}
|
|
29607
30372
|
function verificationText(planText) {
|
|
@@ -29620,7 +30385,7 @@ function parsePrimaryIssueFromMetadata(params) {
|
|
|
29620
30385
|
params.storyText,
|
|
29621
30386
|
params.issueText
|
|
29622
30387
|
]) {
|
|
29623
|
-
for (const line of
|
|
30388
|
+
for (const line of splitLines3(sourceText)) {
|
|
29624
30389
|
const match = pattern.exec(line);
|
|
29625
30390
|
if (match) {
|
|
29626
30391
|
return match[1];
|
|
@@ -29643,20 +30408,20 @@ function parseReadinessValue(text) {
|
|
|
29643
30408
|
}
|
|
29644
30409
|
return null;
|
|
29645
30410
|
}
|
|
29646
|
-
function resolveReadinessSignal(
|
|
29647
|
-
const auditFiles = [...
|
|
30411
|
+
function resolveReadinessSignal(fs10, featureDir) {
|
|
30412
|
+
const auditFiles = [...fs10.glob(featureDir, "feature-audit.*.md")].sort(
|
|
29648
30413
|
compareCodePoint4
|
|
29649
30414
|
);
|
|
29650
30415
|
for (let index = auditFiles.length - 1; index >= 0; index -= 1) {
|
|
29651
30416
|
const auditPath = auditFiles[index];
|
|
29652
|
-
const readiness = parseReadinessValue(readText(
|
|
30417
|
+
const readiness = parseReadinessValue(readText(fs10, auditPath));
|
|
29653
30418
|
if (readiness) {
|
|
29654
30419
|
return [readiness, auditPath];
|
|
29655
30420
|
}
|
|
29656
30421
|
}
|
|
29657
30422
|
return [null, null];
|
|
29658
30423
|
}
|
|
29659
|
-
function
|
|
30424
|
+
function relativeToPosix6(root, path11) {
|
|
29660
30425
|
const normalizedRoot = toPosixPath2(root).replace(/\/+$/u, "");
|
|
29661
30426
|
const normalized = toPosixPath2(path11);
|
|
29662
30427
|
if (normalized.startsWith(`${normalizedRoot}/`)) {
|
|
@@ -29679,22 +30444,26 @@ function escapeRegExp4(value) {
|
|
|
29679
30444
|
|
|
29680
30445
|
// ../../extensions/drm-copilot/src/lib/pr-context/verification-evidence.ts
|
|
29681
30446
|
var REQUIRED_FIELDS = ["Timestamp", "Command", "EXIT_CODE"];
|
|
30447
|
+
var EXPECTED_EXIT_CODE_FIELD = "ExpectedExitCode";
|
|
29682
30448
|
var CANONICAL_GLOBS = [
|
|
29683
30449
|
"evidence/qa-gates/**/*.md",
|
|
29684
30450
|
"evidence/regression-testing/**/*.md",
|
|
29685
30451
|
"evidence/other/**/*.md"
|
|
29686
30452
|
];
|
|
29687
|
-
function
|
|
30453
|
+
function normalizeResult(exitCode, expectedExitCode) {
|
|
30454
|
+
return exitCode === expectedExitCode ? "pass" : "fail";
|
|
30455
|
+
}
|
|
30456
|
+
function discoverCanonicalEvidenceFiles(fs10, root, feature) {
|
|
29688
30457
|
const normalizedRoot = toPosixPath2(root).replace(/\/+$/u, "");
|
|
29689
30458
|
const featureRoot = `${normalizedRoot}/docs/features/active/${feature}`;
|
|
29690
|
-
if (!
|
|
30459
|
+
if (!fs10.exists(featureRoot) || !fs10.isDirectory(featureRoot)) {
|
|
29691
30460
|
return [];
|
|
29692
30461
|
}
|
|
29693
30462
|
const discovered = /* @__PURE__ */ new Set();
|
|
29694
30463
|
for (const pattern of CANONICAL_GLOBS) {
|
|
29695
|
-
for (const candidate of
|
|
29696
|
-
if (
|
|
29697
|
-
discovered.add(
|
|
30464
|
+
for (const candidate of fs10.glob(featureRoot, pattern)) {
|
|
30465
|
+
if (fs10.isFile(candidate)) {
|
|
30466
|
+
discovered.add(relativeToPosix7(normalizedRoot, candidate));
|
|
29698
30467
|
}
|
|
29699
30468
|
}
|
|
29700
30469
|
}
|
|
@@ -29703,7 +30472,7 @@ function discoverCanonicalEvidenceFiles(fs9, root, feature) {
|
|
|
29703
30472
|
function parseVerificationEvidenceMarkdown(params) {
|
|
29704
30473
|
const { feature, sourceFile, markdown } = params;
|
|
29705
30474
|
const parsed = /* @__PURE__ */ new Map();
|
|
29706
|
-
for (const rawLine of
|
|
30475
|
+
for (const rawLine of splitLines6(markdown)) {
|
|
29707
30476
|
const colonIndex = rawLine.indexOf(":");
|
|
29708
30477
|
if (colonIndex === -1) {
|
|
29709
30478
|
continue;
|
|
@@ -29713,10 +30482,14 @@ function parseVerificationEvidenceMarkdown(params) {
|
|
|
29713
30482
|
if (REQUIRED_FIELDS.includes(key) && !parsed.has(key)) {
|
|
29714
30483
|
parsed.set(key, value);
|
|
29715
30484
|
}
|
|
30485
|
+
if (key === EXPECTED_EXIT_CODE_FIELD && !parsed.has(key)) {
|
|
30486
|
+
parsed.set(key, value);
|
|
30487
|
+
}
|
|
29716
30488
|
}
|
|
29717
30489
|
const timestamp = parsed.get("Timestamp") ?? null;
|
|
29718
30490
|
const command = parsed.get("Command") ?? null;
|
|
29719
30491
|
const exitCodeRaw = parsed.get("EXIT_CODE");
|
|
30492
|
+
const expectedExitCodeRaw = parsed.get(EXPECTED_EXIT_CODE_FIELD);
|
|
29720
30493
|
if (!timestamp || !command || exitCodeRaw === void 0) {
|
|
29721
30494
|
return {
|
|
29722
30495
|
feature,
|
|
@@ -29724,7 +30497,8 @@ function parseVerificationEvidenceMarkdown(params) {
|
|
|
29724
30497
|
timestamp,
|
|
29725
30498
|
command,
|
|
29726
30499
|
exitCode: null,
|
|
29727
|
-
normalizedResult: "unparseable"
|
|
30500
|
+
normalizedResult: "unparseable",
|
|
30501
|
+
expectedExitCode: 0
|
|
29728
30502
|
};
|
|
29729
30503
|
}
|
|
29730
30504
|
const exitCode = parseIntegerStrict(exitCodeRaw);
|
|
@@ -29735,24 +30509,41 @@ function parseVerificationEvidenceMarkdown(params) {
|
|
|
29735
30509
|
timestamp,
|
|
29736
30510
|
command,
|
|
29737
30511
|
exitCode: null,
|
|
29738
|
-
normalizedResult: "unparseable"
|
|
30512
|
+
normalizedResult: "unparseable",
|
|
30513
|
+
expectedExitCode: 0
|
|
30514
|
+
};
|
|
30515
|
+
}
|
|
30516
|
+
const expectedExitCode = expectedExitCodeRaw === void 0 ? 0 : parseIntegerStrict(expectedExitCodeRaw);
|
|
30517
|
+
if (expectedExitCode === null) {
|
|
30518
|
+
return {
|
|
30519
|
+
feature,
|
|
30520
|
+
sourceFile,
|
|
30521
|
+
timestamp,
|
|
30522
|
+
command,
|
|
30523
|
+
exitCode: null,
|
|
30524
|
+
normalizedResult: "unparseable",
|
|
30525
|
+
expectedExitCode: 0
|
|
29739
30526
|
};
|
|
29740
30527
|
}
|
|
29741
|
-
const normalizedResult =
|
|
30528
|
+
const normalizedResult = normalizeResult(
|
|
30529
|
+
exitCode,
|
|
30530
|
+
expectedExitCode
|
|
30531
|
+
);
|
|
29742
30532
|
return {
|
|
29743
30533
|
feature,
|
|
29744
30534
|
sourceFile,
|
|
29745
30535
|
timestamp,
|
|
29746
30536
|
command,
|
|
29747
30537
|
exitCode,
|
|
29748
|
-
normalizedResult
|
|
30538
|
+
normalizedResult,
|
|
30539
|
+
expectedExitCode
|
|
29749
30540
|
};
|
|
29750
30541
|
}
|
|
29751
30542
|
function parseVerificationEvidenceFile(params) {
|
|
29752
|
-
const { fs:
|
|
30543
|
+
const { fs: fs10, root, feature, relativePath: relativePath2 } = params;
|
|
29753
30544
|
const normalizedRoot = toPosixPath2(root).replace(/\/+$/u, "");
|
|
29754
30545
|
const relPosix = toPosixPath2(relativePath2).replace(/^\/+/u, "");
|
|
29755
|
-
const markdown =
|
|
30546
|
+
const markdown = fs10.readTextFile(`${normalizedRoot}/${relPosix}`);
|
|
29756
30547
|
return parseVerificationEvidenceMarkdown({
|
|
29757
30548
|
feature,
|
|
29758
30549
|
sourceFile: relPosix,
|
|
@@ -29765,7 +30556,7 @@ function parseIntegerStrict(value) {
|
|
|
29765
30556
|
}
|
|
29766
30557
|
return Number.parseInt(value, 10);
|
|
29767
30558
|
}
|
|
29768
|
-
function
|
|
30559
|
+
function relativeToPosix7(root, absolute) {
|
|
29769
30560
|
const normalized = toPosixPath2(absolute);
|
|
29770
30561
|
if (normalized.startsWith(`${root}/`)) {
|
|
29771
30562
|
return normalized.slice(root.length + 1);
|
|
@@ -29781,7 +30572,7 @@ function compareCodePoint5(left, right) {
|
|
|
29781
30572
|
}
|
|
29782
30573
|
return 0;
|
|
29783
30574
|
}
|
|
29784
|
-
function
|
|
30575
|
+
function splitLines6(value) {
|
|
29785
30576
|
if (value === "") {
|
|
29786
30577
|
return [];
|
|
29787
30578
|
}
|
|
@@ -29814,15 +30605,15 @@ function extractFeatures3(changedFiles) {
|
|
|
29814
30605
|
}
|
|
29815
30606
|
return features;
|
|
29816
30607
|
}
|
|
29817
|
-
function gatherFeatureExcerpts2(
|
|
30608
|
+
function gatherFeatureExcerpts2(fs10, root, changedFiles) {
|
|
29818
30609
|
const normalizedRoot = toPosixPath2(root).replace(/\/+$/u, "");
|
|
29819
30610
|
const features = extractFeatures3(changedFiles);
|
|
29820
30611
|
const excerpts = [];
|
|
29821
30612
|
const baseDir = `${normalizedRoot}/docs/features/active`;
|
|
29822
30613
|
const promotedDir = `${normalizedRoot}/docs/features/potential/promoted`;
|
|
29823
30614
|
for (const feature of [...features].sort(compareCodePoint4)) {
|
|
29824
|
-
const featureDir = resolveFeatureDir2(
|
|
29825
|
-
const promotedFeatureDir = resolveFeatureDir2(
|
|
30615
|
+
const featureDir = resolveFeatureDir2(fs10, baseDir, feature);
|
|
30616
|
+
const promotedFeatureDir = resolveFeatureDir2(fs10, promotedDir, feature);
|
|
29826
30617
|
if (featureDir === null && promotedFeatureDir === null) {
|
|
29827
30618
|
continue;
|
|
29828
30619
|
}
|
|
@@ -29833,33 +30624,33 @@ function gatherFeatureExcerpts2(fs9, root, changedFiles) {
|
|
|
29833
30624
|
const specPath = `${activeDir}/spec.md`;
|
|
29834
30625
|
const issuePath = `${activeDir}/issue.md`;
|
|
29835
30626
|
let planPath = `${activeDir}/plan.md`;
|
|
29836
|
-
if (!
|
|
29837
|
-
const latestPlan = latestGlobPath(
|
|
30627
|
+
if (!fs10.exists(planPath)) {
|
|
30628
|
+
const latestPlan = latestGlobPath(fs10, activeDir, "plan.*.md");
|
|
29838
30629
|
if (latestPlan !== null) {
|
|
29839
30630
|
planPath = latestPlan;
|
|
29840
30631
|
}
|
|
29841
30632
|
}
|
|
29842
30633
|
let userStoryPath = `${activeDir}/user-story.md`;
|
|
29843
30634
|
const promotedStoryPath = promotedFeatureDir !== null ? `${promotedFeatureDir}/user-story.md` : null;
|
|
29844
|
-
const promotedStoryText = promotedStoryPath !== null ? readText(
|
|
29845
|
-
if (promotedStoryPath !== null && !
|
|
30635
|
+
const promotedStoryText = promotedStoryPath !== null ? readText(fs10, promotedStoryPath) : "";
|
|
30636
|
+
if (promotedStoryPath !== null && !fs10.exists(userStoryPath)) {
|
|
29846
30637
|
userStoryPath = promotedStoryPath;
|
|
29847
30638
|
}
|
|
29848
|
-
let userStoryText = readText(
|
|
30639
|
+
let userStoryText = readText(fs10, userStoryPath);
|
|
29849
30640
|
if (!userStoryText && promotedStoryText && promotedStoryPath !== null) {
|
|
29850
30641
|
userStoryText = promotedStoryText;
|
|
29851
30642
|
userStoryPath = promotedStoryPath;
|
|
29852
30643
|
}
|
|
29853
|
-
const specText = readText(
|
|
29854
|
-
const issueText = readText(
|
|
29855
|
-
const planText = readText(
|
|
30644
|
+
const specText = readText(fs10, specPath);
|
|
30645
|
+
const issueText = readText(fs10, issuePath);
|
|
30646
|
+
const planText = readText(fs10, planPath);
|
|
29856
30647
|
const primaryIssueRef = parsePrimaryIssueFromMetadata({
|
|
29857
30648
|
specText,
|
|
29858
30649
|
storyText: userStoryText,
|
|
29859
30650
|
issueText
|
|
29860
30651
|
});
|
|
29861
30652
|
const [readinessSignal, readinessSource] = resolveReadinessSignal(
|
|
29862
|
-
|
|
30653
|
+
fs10,
|
|
29863
30654
|
activeDir
|
|
29864
30655
|
);
|
|
29865
30656
|
const specParts = buildSpecParts(specText);
|
|
@@ -29874,7 +30665,7 @@ function gatherFeatureExcerpts2(fs9, root, changedFiles) {
|
|
|
29874
30665
|
verificationBlock
|
|
29875
30666
|
);
|
|
29876
30667
|
const contextFiles = buildContextFiles({
|
|
29877
|
-
fs:
|
|
30668
|
+
fs: fs10,
|
|
29878
30669
|
root: normalizedRoot,
|
|
29879
30670
|
feature,
|
|
29880
30671
|
candidatePaths: [specPath, issuePath, planPath, userStoryPath],
|
|
@@ -29958,18 +30749,18 @@ function buildExcerpt(feature, storyParts, specParts, planSection, verificationB
|
|
|
29958
30749
|
return lines.join("\n");
|
|
29959
30750
|
}
|
|
29960
30751
|
function buildContextFiles(params) {
|
|
29961
|
-
const { fs:
|
|
30752
|
+
const { fs: fs10, root, feature, candidatePaths, readinessSource } = params;
|
|
29962
30753
|
const contextFiles = [];
|
|
29963
30754
|
for (const path11 of candidatePaths) {
|
|
29964
|
-
if (
|
|
29965
|
-
contextFiles.push(
|
|
30755
|
+
if (fs10.exists(path11)) {
|
|
30756
|
+
contextFiles.push(relativeToPosix6(root, path11));
|
|
29966
30757
|
}
|
|
29967
30758
|
}
|
|
29968
30759
|
if (readinessSource !== null) {
|
|
29969
|
-
contextFiles.push(
|
|
30760
|
+
contextFiles.push(relativeToPosix6(root, readinessSource));
|
|
29970
30761
|
}
|
|
29971
30762
|
const evidenceContextFiles = discoverCanonicalEvidenceFiles(
|
|
29972
|
-
|
|
30763
|
+
fs10,
|
|
29973
30764
|
root,
|
|
29974
30765
|
feature
|
|
29975
30766
|
);
|
|
@@ -30003,7 +30794,7 @@ function extractDigestBullets(body, headings, limit) {
|
|
|
30003
30794
|
if (!sectionText) {
|
|
30004
30795
|
continue;
|
|
30005
30796
|
}
|
|
30006
|
-
for (const line of
|
|
30797
|
+
for (const line of splitLines3(sectionText)) {
|
|
30007
30798
|
if (!line.trim()) {
|
|
30008
30799
|
continue;
|
|
30009
30800
|
}
|
|
@@ -30144,7 +30935,7 @@ function parseNumstatDetailed(numstatText) {
|
|
|
30144
30935
|
let addsTotal = 0;
|
|
30145
30936
|
let delsTotal = 0;
|
|
30146
30937
|
const perFile = /* @__PURE__ */ new Map();
|
|
30147
|
-
for (const rawLine of
|
|
30938
|
+
for (const rawLine of splitLines3(numstatText)) {
|
|
30148
30939
|
if (!rawLine.trim()) {
|
|
30149
30940
|
continue;
|
|
30150
30941
|
}
|
|
@@ -30163,7 +30954,7 @@ function parseNumstatDetailed(numstatText) {
|
|
|
30163
30954
|
}
|
|
30164
30955
|
function parseNameStatusMap(nameStatusText) {
|
|
30165
30956
|
const mapping = /* @__PURE__ */ new Map();
|
|
30166
|
-
for (const rawLine of
|
|
30957
|
+
for (const rawLine of splitLines3(nameStatusText)) {
|
|
30167
30958
|
if (!rawLine.trim()) {
|
|
30168
30959
|
continue;
|
|
30169
30960
|
}
|
|
@@ -30182,7 +30973,7 @@ function isScopingDoc(path11) {
|
|
|
30182
30973
|
return lowered.startsWith("docs/features/") && (lowered.endsWith("/spec.md") || lowered.endsWith("/plan.md") || lowered.endsWith("/bug-remediation-plan.md") || lowered.endsWith("/user-story.md") || lowered.endsWith("/readme.md"));
|
|
30183
30974
|
}
|
|
30184
30975
|
function scopingDocChanges(options) {
|
|
30185
|
-
const { git, fs:
|
|
30976
|
+
const { git, fs: fs10, mergeBase, headSha, root, nameStatusText, numstatDetails } = options;
|
|
30186
30977
|
if (!mergeBase || !headSha) {
|
|
30187
30978
|
return [];
|
|
30188
30979
|
}
|
|
@@ -30211,7 +31002,7 @@ function scopingDocChanges(options) {
|
|
|
30211
31002
|
path11
|
|
30212
31003
|
]);
|
|
30213
31004
|
let headingTouched = false;
|
|
30214
|
-
for (const line of
|
|
31005
|
+
for (const line of splitLines3(diffText)) {
|
|
30215
31006
|
if (!line.startsWith("+") || line.startsWith("+++")) {
|
|
30216
31007
|
continue;
|
|
30217
31008
|
}
|
|
@@ -30227,7 +31018,7 @@ function scopingDocChanges(options) {
|
|
|
30227
31018
|
material = true;
|
|
30228
31019
|
reasons.push("key section touched");
|
|
30229
31020
|
}
|
|
30230
|
-
const addedLines =
|
|
31021
|
+
const addedLines = splitLines3(diffText).filter((line) => line.startsWith("+") && !line.startsWith("+++")).map((line) => line.replace(/^\++/u, "").trim());
|
|
30231
31022
|
if (addedLines.length > 0 && addedLines.every(
|
|
30232
31023
|
(line) => !line || line.startsWith("[") || line.startsWith("http")
|
|
30233
31024
|
)) {
|
|
@@ -30238,8 +31029,8 @@ function scopingDocChanges(options) {
|
|
|
30238
31029
|
}
|
|
30239
31030
|
let excerpt = null;
|
|
30240
31031
|
const docPath = `${stripTrailingSlash(root)}/${path11}`;
|
|
30241
|
-
if (material &&
|
|
30242
|
-
const content =
|
|
31032
|
+
if (material && fs10.exists(docPath)) {
|
|
31033
|
+
const content = fs10.readTextFile(docPath);
|
|
30243
31034
|
const excerptParts = [];
|
|
30244
31035
|
for (const heading of SCOPING_EXCERPT_HEADINGS) {
|
|
30245
31036
|
const sectionText = parseSection3(content, heading);
|
|
@@ -30315,16 +31106,16 @@ function isDigits2(value) {
|
|
|
30315
31106
|
var SUMMARY_CHAR_BUDGET = 16e4;
|
|
30316
31107
|
var APPENDIX_CHAR_BUDGET = 48e4;
|
|
30317
31108
|
function collectPrContext(options) {
|
|
30318
|
-
const { base, repoRoot, includeUntracked, fs:
|
|
31109
|
+
const { base, repoRoot, includeUntracked, fs: fs10, runner } = options;
|
|
30319
31110
|
const head = options.head ?? null;
|
|
30320
31111
|
const whichGh = options.whichGh;
|
|
30321
|
-
let git = new GitClient(runner, repoRoot,
|
|
31112
|
+
let git = new GitClient(runner, repoRoot, fs10);
|
|
30322
31113
|
const resolvedRoot = git.resolveRoot();
|
|
30323
|
-
git = new GitClient(runner, resolvedRoot,
|
|
31114
|
+
git = new GitClient(runner, resolvedRoot, fs10);
|
|
30324
31115
|
const gh = new GhClient({
|
|
30325
31116
|
runner,
|
|
30326
31117
|
cwd: resolvedRoot,
|
|
30327
|
-
fileSystem:
|
|
31118
|
+
fileSystem: fs10,
|
|
30328
31119
|
...whichGh === void 0 ? {} : { whichGh }
|
|
30329
31120
|
});
|
|
30330
31121
|
let ghAvailable = true;
|
|
@@ -30347,7 +31138,7 @@ function collectPrContext(options) {
|
|
|
30347
31138
|
ghAvailable
|
|
30348
31139
|
});
|
|
30349
31140
|
const changedPaths = extractChangedPaths(contextResult.text);
|
|
30350
|
-
const featureDocs = gatherFeatureExcerpts2(
|
|
31141
|
+
const featureDocs = gatherFeatureExcerpts2(fs10, resolvedRoot, changedPaths);
|
|
30351
31142
|
const additionalContextFiles = sortedSet3(
|
|
30352
31143
|
featureDocs.flatMap((doc) => doc.contextFiles).filter((path11) => path11)
|
|
30353
31144
|
);
|
|
@@ -30460,7 +31251,7 @@ function collectPrContext(options) {
|
|
|
30460
31251
|
const statusMap = parseNameStatusMap(nameStatusText);
|
|
30461
31252
|
const scopingChanges = scopingDocChanges({
|
|
30462
31253
|
git,
|
|
30463
|
-
fs:
|
|
31254
|
+
fs: fs10,
|
|
30464
31255
|
mergeBase: contextResult.mergeBase,
|
|
30465
31256
|
headSha: contextResult.headSha,
|
|
30466
31257
|
root: resolvedRoot,
|
|
@@ -30594,7 +31385,7 @@ function compareCodePoint6(left, right) {
|
|
|
30594
31385
|
}
|
|
30595
31386
|
|
|
30596
31387
|
// ../../extensions/drm-copilot/src/lib/pr-context/collector-output.ts
|
|
30597
|
-
function renderVerificationEvidenceSection(
|
|
31388
|
+
function renderVerificationEvidenceSection(fs10, resolvedRoot, featureDocs) {
|
|
30598
31389
|
const records = [];
|
|
30599
31390
|
for (const doc of featureDocs) {
|
|
30600
31391
|
for (const rawPath of doc.contextFiles) {
|
|
@@ -30605,7 +31396,7 @@ function renderVerificationEvidenceSection(fs9, resolvedRoot, featureDocs) {
|
|
|
30605
31396
|
try {
|
|
30606
31397
|
records.push(
|
|
30607
31398
|
parseVerificationEvidenceFile({
|
|
30608
|
-
fs:
|
|
31399
|
+
fs: fs10,
|
|
30609
31400
|
root: resolvedRoot,
|
|
30610
31401
|
feature: doc.feature,
|
|
30611
31402
|
relativePath: normalized
|
|
@@ -30627,18 +31418,21 @@ function renderVerificationEvidenceSection(fs9, resolvedRoot, featureDocs) {
|
|
|
30627
31418
|
(left, right) => left.sourceFile < right.sourceFile ? -1 : left.sourceFile > right.sourceFile ? 1 : 0
|
|
30628
31419
|
);
|
|
30629
31420
|
for (const record2 of sorted) {
|
|
31421
|
+
const expected = record2.expectedExitCode;
|
|
31422
|
+
const expectedRows = expected === 0 ? [] : [` - Expected EXIT_CODE: ${String(expected)}`];
|
|
30630
31423
|
lines.push(
|
|
30631
31424
|
`- Feature: ${record2.feature}`,
|
|
30632
31425
|
` - Source: ${record2.sourceFile}`,
|
|
30633
31426
|
` - Timestamp: ${record2.timestamp}`,
|
|
30634
31427
|
` - Command: ${record2.command}`,
|
|
30635
31428
|
` - EXIT_CODE: ${record2.exitCode}`,
|
|
31429
|
+
...expectedRows,
|
|
30636
31430
|
` - Normalized result: ${record2.normalizedResult}`
|
|
30637
31431
|
);
|
|
30638
31432
|
}
|
|
30639
31433
|
return lines.join("\n");
|
|
30640
31434
|
}
|
|
30641
|
-
function buildSummaryText(collected,
|
|
31435
|
+
function buildSummaryText(collected, fs10, appendixPath) {
|
|
30642
31436
|
const ctx = collected.contextResult;
|
|
30643
31437
|
const ghStatusText = resolveGhStatusText(collected);
|
|
30644
31438
|
const intentBlock = [
|
|
@@ -30668,7 +31462,7 @@ function buildSummaryText(collected, fs9, appendixPath) {
|
|
|
30668
31462
|
const prDigests = collected.prDetailsList.map((detail) => prDigest(detail)).join("\n\n");
|
|
30669
31463
|
const featureSummary = buildFeatureSummary(collected.featureDocs);
|
|
30670
31464
|
const verificationEvidenceSection = renderVerificationEvidenceSection(
|
|
30671
|
-
|
|
31465
|
+
fs10,
|
|
30672
31466
|
collected.resolvedRoot,
|
|
30673
31467
|
collected.featureDocs
|
|
30674
31468
|
);
|
|
@@ -30753,16 +31547,16 @@ function buildAppendixText(collected, clock) {
|
|
|
30753
31547
|
}
|
|
30754
31548
|
return appendixText;
|
|
30755
31549
|
}
|
|
30756
|
-
function writeOutput(
|
|
31550
|
+
function writeOutput(fs10, text, outPath, append) {
|
|
30757
31551
|
const parent = parentDir(outPath);
|
|
30758
31552
|
if (parent) {
|
|
30759
|
-
|
|
31553
|
+
fs10.ensureDir(parent);
|
|
30760
31554
|
}
|
|
30761
|
-
if (append &&
|
|
30762
|
-
const existing =
|
|
30763
|
-
|
|
31555
|
+
if (append && fs10.isFile(outPath)) {
|
|
31556
|
+
const existing = fs10.readTextFile(outPath);
|
|
31557
|
+
fs10.writeTextFile(outPath, existing + text);
|
|
30764
31558
|
} else {
|
|
30765
|
-
|
|
31559
|
+
fs10.writeTextFile(outPath, text);
|
|
30766
31560
|
}
|
|
30767
31561
|
}
|
|
30768
31562
|
function collectAndWrite(options) {
|
|
@@ -31206,7 +32000,7 @@ function normalizeSmartPunctuation(text) {
|
|
|
31206
32000
|
var nodePath7 = __toESM(require("node:path"));
|
|
31207
32001
|
|
|
31208
32002
|
// ../../extensions/drm-copilot/src/lib/potential-to-issue/promotion-filesystem.ts
|
|
31209
|
-
var
|
|
32003
|
+
var fs7 = __toESM(require("node:fs"));
|
|
31210
32004
|
var nodeOs = __toESM(require("node:os"));
|
|
31211
32005
|
var nodePath6 = __toESM(require("node:path"));
|
|
31212
32006
|
var RealPotentialFileSystem = class {
|
|
@@ -31223,24 +32017,24 @@ var RealPotentialFileSystem = class {
|
|
|
31223
32017
|
}
|
|
31224
32018
|
/** @returns True when `path` exists. */
|
|
31225
32019
|
exists(path11) {
|
|
31226
|
-
return
|
|
32020
|
+
return fs7.existsSync(path11);
|
|
31227
32021
|
}
|
|
31228
32022
|
/** @returns The UTF-8 file content. */
|
|
31229
32023
|
readText(path11) {
|
|
31230
|
-
return
|
|
32024
|
+
return fs7.readFileSync(path11, "utf8");
|
|
31231
32025
|
}
|
|
31232
32026
|
/** Write `lines` joined with `\n` as UTF-8 text. */
|
|
31233
32027
|
writeLines(path11, lines) {
|
|
31234
|
-
|
|
32028
|
+
fs7.writeFileSync(path11, lines.join("\n"), "utf8");
|
|
31235
32029
|
}
|
|
31236
32030
|
/** Create `path` and any missing parents (idempotent). */
|
|
31237
32031
|
ensureDir(path11) {
|
|
31238
|
-
|
|
32032
|
+
fs7.mkdirSync(path11, { recursive: true });
|
|
31239
32033
|
}
|
|
31240
32034
|
/** Move `src` to `dest`, ensuring the destination parent exists first. */
|
|
31241
32035
|
move(src, dest) {
|
|
31242
|
-
|
|
31243
|
-
|
|
32036
|
+
fs7.mkdirSync(nodePath6.dirname(dest), { recursive: true });
|
|
32037
|
+
fs7.renameSync(src, dest);
|
|
31244
32038
|
}
|
|
31245
32039
|
};
|
|
31246
32040
|
|
|
@@ -31465,12 +32259,13 @@ var CommandRunnerGhAdapter = class {
|
|
|
31465
32259
|
};
|
|
31466
32260
|
function potentialToIssueServiceCall(input) {
|
|
31467
32261
|
const ghClient = input.gh ?? new RealGhClient({ runner: new CommandRunnerGhAdapter(input.runner) });
|
|
32262
|
+
const fileSystem = input.fileSystem ?? new RealPotentialFileSystem();
|
|
31468
32263
|
const outcome = promotePotential({
|
|
31469
32264
|
potentialPath: input.potentialPath,
|
|
31470
32265
|
promotionType: input.promotionType,
|
|
31471
32266
|
workMode: input.workMode,
|
|
31472
32267
|
workspace: input.workspaceRoot,
|
|
31473
|
-
fs:
|
|
32268
|
+
fs: fileSystem,
|
|
31474
32269
|
gh: ghClient,
|
|
31475
32270
|
...input.log === void 0 ? {} : { emit: input.log }
|
|
31476
32271
|
});
|
|
@@ -31481,6 +32276,11 @@ ${outcome.messages.join("\n")}` : "";
|
|
|
31481
32276
|
}
|
|
31482
32277
|
const summary = `Promoted '${input.potentialPath}' as a ${input.promotionType} workflow in ${input.workMode} mode.`;
|
|
31483
32278
|
const [issueUrl] = parseIssueReference(outcome.messages);
|
|
32279
|
+
if (outcome.destination !== void 0 && !fileSystem.exists(outcome.destination)) {
|
|
32280
|
+
throw new Error(
|
|
32281
|
+
`potential_to_issue reported a path that does not exist: ${outcome.destination}`
|
|
32282
|
+
);
|
|
32283
|
+
}
|
|
31484
32284
|
return {
|
|
31485
32285
|
tool: "potential_to_issue",
|
|
31486
32286
|
workspaceRoot: input.workspaceRoot,
|
|
@@ -31667,12 +32467,12 @@ function validateFeatureName2(featureName) {
|
|
|
31667
32467
|
function escapeRegExp6(value) {
|
|
31668
32468
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
31669
32469
|
}
|
|
31670
|
-
function
|
|
32470
|
+
function splitLines7(text) {
|
|
31671
32471
|
return text.split(/\r\n|\r|\n/);
|
|
31672
32472
|
}
|
|
31673
32473
|
function formatChecklist(text) {
|
|
31674
32474
|
const lines = [];
|
|
31675
|
-
for (const rawLine of
|
|
32475
|
+
for (const rawLine of splitLines7(text)) {
|
|
31676
32476
|
const trimmed = rawLine.trim();
|
|
31677
32477
|
if (!trimmed) {
|
|
31678
32478
|
continue;
|
|
@@ -31701,7 +32501,7 @@ function getSection2(content, name) {
|
|
|
31701
32501
|
function upsertWorkModeMarker(content, mode) {
|
|
31702
32502
|
const markerLine = `- Work Mode: ${mode}`;
|
|
31703
32503
|
const markerPattern = /^- Work Mode:\s*(minor-audit|full-feature|full-bug|full)\s*$/;
|
|
31704
|
-
const lines =
|
|
32504
|
+
const lines = splitLines7(content).filter((line) => !markerPattern.test(line));
|
|
31705
32505
|
for (let idx = 0; idx < lines.length; idx += 1) {
|
|
31706
32506
|
const line = lines[idx] ?? "";
|
|
31707
32507
|
if (line.replace(/^\s+/, "").startsWith("## ")) {
|
|
@@ -31886,7 +32686,7 @@ function replaceRegexLiteral(source, pattern, replacement) {
|
|
|
31886
32686
|
}
|
|
31887
32687
|
|
|
31888
32688
|
// ../../extensions/drm-copilot/src/lib/new-active-feature-folder/io-launcher.ts
|
|
31889
|
-
var
|
|
32689
|
+
var fs8 = __toESM(require("node:fs"));
|
|
31890
32690
|
var nodePath9 = __toESM(require("node:path"));
|
|
31891
32691
|
var INSIDERS_SIGNAL_NAMES2 = [
|
|
31892
32692
|
"TERM_PROGRAM_VERSION",
|
|
@@ -31904,7 +32704,7 @@ function defaultWhichLookup2(executable) {
|
|
|
31904
32704
|
directory,
|
|
31905
32705
|
process.platform === "win32" ? `${executable}${extension}` : executable
|
|
31906
32706
|
);
|
|
31907
|
-
if (
|
|
32707
|
+
if (fs8.existsSync(candidate)) {
|
|
31908
32708
|
return candidate;
|
|
31909
32709
|
}
|
|
31910
32710
|
}
|
|
@@ -31973,14 +32773,14 @@ function stem(path11) {
|
|
|
31973
32773
|
const ext = suffix(path11);
|
|
31974
32774
|
return ext ? name.slice(0, name.length - ext.length) : name;
|
|
31975
32775
|
}
|
|
31976
|
-
function findPotentialFile(featureName, workspace2,
|
|
32776
|
+
function findPotentialFile(featureName, workspace2, fs10) {
|
|
31977
32777
|
const normalized = featureName.replace(/_/g, "-");
|
|
31978
32778
|
const potentialDirs = [
|
|
31979
32779
|
joinPosix13(workspace2, "docs/features/potential"),
|
|
31980
32780
|
joinPosix13(workspace2, "docs/features/potential/promoted")
|
|
31981
32781
|
];
|
|
31982
32782
|
for (const directory of potentialDirs) {
|
|
31983
|
-
const candidates =
|
|
32783
|
+
const candidates = fs10.listFiles(directory).filter(
|
|
31984
32784
|
(file) => suffix(file) === ".md" && baseName(file).includes(normalized) && !EXCLUDED_POTENTIAL_NAMES.has(baseName(file))
|
|
31985
32785
|
);
|
|
31986
32786
|
if (candidates.length > 0) {
|
|
@@ -32011,12 +32811,12 @@ function buildFolderSlug(featureName, potentialFile, issueNumber) {
|
|
|
32011
32811
|
}
|
|
32012
32812
|
return slug;
|
|
32013
32813
|
}
|
|
32014
|
-
function copyTemplate(featureType, templateDir, targetDir,
|
|
32814
|
+
function copyTemplate(featureType, templateDir, targetDir, fs10) {
|
|
32015
32815
|
if (featureType === "bug") {
|
|
32016
32816
|
for (const name of ["spec.md", PLAN_TIMESTAMP_TEMPLATE_NAME, "plan.md"]) {
|
|
32017
32817
|
const src = joinPosix13(templateDir, name);
|
|
32018
|
-
if (
|
|
32019
|
-
|
|
32818
|
+
if (fs10.exists(src)) {
|
|
32819
|
+
fs10.copyFile(src, joinPosix13(targetDir, name));
|
|
32020
32820
|
if (name === PLAN_TIMESTAMP_TEMPLATE_NAME) {
|
|
32021
32821
|
break;
|
|
32022
32822
|
}
|
|
@@ -32025,35 +32825,35 @@ function copyTemplate(featureType, templateDir, targetDir, fs9) {
|
|
|
32025
32825
|
} else if (featureType === "epic") {
|
|
32026
32826
|
for (const name of ["epic.md", "epic-status.md"]) {
|
|
32027
32827
|
const src = joinPosix13(templateDir, name);
|
|
32028
|
-
if (
|
|
32029
|
-
|
|
32828
|
+
if (fs10.exists(src)) {
|
|
32829
|
+
fs10.copyFile(src, joinPosix13(targetDir, name));
|
|
32030
32830
|
}
|
|
32031
32831
|
}
|
|
32032
32832
|
} else {
|
|
32033
|
-
|
|
32833
|
+
fs10.copyTree(templateDir, targetDir);
|
|
32034
32834
|
}
|
|
32035
32835
|
}
|
|
32036
|
-
function copyFeatureTemplateForMinorAudit(templateDir, targetDir,
|
|
32836
|
+
function copyFeatureTemplateForMinorAudit(templateDir, targetDir, fs10) {
|
|
32037
32837
|
const timestampedPlan = joinPosix13(templateDir, PLAN_TIMESTAMP_TEMPLATE_NAME);
|
|
32038
|
-
if (
|
|
32039
|
-
|
|
32838
|
+
if (fs10.exists(timestampedPlan)) {
|
|
32839
|
+
fs10.copyFile(
|
|
32040
32840
|
timestampedPlan,
|
|
32041
32841
|
joinPosix13(targetDir, PLAN_TIMESTAMP_TEMPLATE_NAME)
|
|
32042
32842
|
);
|
|
32043
32843
|
return;
|
|
32044
32844
|
}
|
|
32045
32845
|
const legacyPlan = joinPosix13(templateDir, "plan.md");
|
|
32046
|
-
if (
|
|
32047
|
-
|
|
32846
|
+
if (fs10.exists(legacyPlan)) {
|
|
32847
|
+
fs10.copyFile(legacyPlan, joinPosix13(targetDir, "plan.md"));
|
|
32048
32848
|
}
|
|
32049
32849
|
}
|
|
32050
|
-
function materializePlanFile(featureType, targetDir, featureName, issueField, ownerField, parentField, statusField, versionField, planTimestamp,
|
|
32850
|
+
function materializePlanFile(featureType, targetDir, featureName, issueField, ownerField, parentField, statusField, versionField, planTimestamp, fs10) {
|
|
32051
32851
|
void featureType;
|
|
32052
32852
|
const templatePlan = joinPosix13(targetDir, PLAN_TIMESTAMP_TEMPLATE_NAME);
|
|
32053
|
-
if (
|
|
32853
|
+
if (fs10.exists(templatePlan)) {
|
|
32054
32854
|
const targetPlan = joinPosix13(targetDir, `plan.${planTimestamp}.md`);
|
|
32055
|
-
|
|
32056
|
-
let content =
|
|
32855
|
+
fs10.move(templatePlan, targetPlan);
|
|
32856
|
+
let content = fs10.readText(targetPlan);
|
|
32057
32857
|
const updatedField = planTimestamp;
|
|
32058
32858
|
content = setHeaderPlaceholder(
|
|
32059
32859
|
content,
|
|
@@ -32065,11 +32865,11 @@ function materializePlanFile(featureType, targetDir, featureName, issueField, ow
|
|
|
32065
32865
|
parentField,
|
|
32066
32866
|
versionField
|
|
32067
32867
|
);
|
|
32068
|
-
|
|
32868
|
+
fs10.writeText(targetPlan, content);
|
|
32069
32869
|
return targetPlan;
|
|
32070
32870
|
}
|
|
32071
32871
|
const legacy = joinPosix13(targetDir, "plan.md");
|
|
32072
|
-
if (
|
|
32872
|
+
if (fs10.exists(legacy)) {
|
|
32073
32873
|
return legacy;
|
|
32074
32874
|
}
|
|
32075
32875
|
return null;
|
|
@@ -32114,11 +32914,11 @@ function defaultIssueFetcher(issueNumber, runner, ghLookup = defaultGhLookup) {
|
|
|
32114
32914
|
}
|
|
32115
32915
|
|
|
32116
32916
|
// ../../extensions/drm-copilot/src/lib/new-active-feature-folder/docs.ts
|
|
32117
|
-
function applyHeaderAndSections(path11, featureName, issueField, ownerField, updatedField, parentField, statusField, versionField,
|
|
32118
|
-
if (!
|
|
32917
|
+
function applyHeaderAndSections(path11, featureName, issueField, ownerField, updatedField, parentField, statusField, versionField, fs10, updates) {
|
|
32918
|
+
if (!fs10.exists(path11)) {
|
|
32119
32919
|
return;
|
|
32120
32920
|
}
|
|
32121
|
-
let content =
|
|
32921
|
+
let content = fs10.readText(path11);
|
|
32122
32922
|
content = setHeaderPlaceholder(
|
|
32123
32923
|
content,
|
|
32124
32924
|
featureName,
|
|
@@ -32132,9 +32932,9 @@ function applyHeaderAndSections(path11, featureName, issueField, ownerField, upd
|
|
|
32132
32932
|
for (const [sectionName, body] of updates) {
|
|
32133
32933
|
content = setSection(content, sectionName, body);
|
|
32134
32934
|
}
|
|
32135
|
-
|
|
32935
|
+
fs10.writeText(path11, content);
|
|
32136
32936
|
}
|
|
32137
|
-
function updateFeatureDocs(featureType, featureName, targetDir, issueField, ownerField, updatedField, parentField, statusField, versionField, planUpdatedField,
|
|
32937
|
+
function updateFeatureDocs(featureType, featureName, targetDir, issueField, ownerField, updatedField, parentField, statusField, versionField, planUpdatedField, fs10, sections, planPath) {
|
|
32138
32938
|
const filesToOpen = [];
|
|
32139
32939
|
const get = (key) => sections[key] ?? "";
|
|
32140
32940
|
if (featureType === "feature") {
|
|
@@ -32150,7 +32950,7 @@ function updateFeatureDocs(featureType, featureName, targetDir, issueField, owne
|
|
|
32150
32950
|
parentField,
|
|
32151
32951
|
statusField,
|
|
32152
32952
|
versionField,
|
|
32153
|
-
|
|
32953
|
+
fs10,
|
|
32154
32954
|
[
|
|
32155
32955
|
["Problem / Why", get("problem")],
|
|
32156
32956
|
["Acceptance Criteria", formatChecklist(get("criteria"))]
|
|
@@ -32165,7 +32965,7 @@ function updateFeatureDocs(featureType, featureName, targetDir, issueField, owne
|
|
|
32165
32965
|
parentField,
|
|
32166
32966
|
statusField,
|
|
32167
32967
|
versionField,
|
|
32168
|
-
|
|
32968
|
+
fs10,
|
|
32169
32969
|
[
|
|
32170
32970
|
["Overview", get("problem")],
|
|
32171
32971
|
["Behavior", get("behavior")],
|
|
@@ -32185,7 +32985,7 @@ function updateFeatureDocs(featureType, featureName, targetDir, issueField, owne
|
|
|
32185
32985
|
parentField,
|
|
32186
32986
|
statusField,
|
|
32187
32987
|
versionField,
|
|
32188
|
-
|
|
32988
|
+
fs10,
|
|
32189
32989
|
[]
|
|
32190
32990
|
);
|
|
32191
32991
|
filesToOpen.push(userStory, spec, plan);
|
|
@@ -32201,7 +33001,7 @@ function updateFeatureDocs(featureType, featureName, targetDir, issueField, owne
|
|
|
32201
33001
|
parentField,
|
|
32202
33002
|
statusField,
|
|
32203
33003
|
versionField,
|
|
32204
|
-
|
|
33004
|
+
fs10,
|
|
32205
33005
|
[
|
|
32206
33006
|
["Intent & Outcomes", get("problem")],
|
|
32207
33007
|
["Scope (structural changes)", get("behavior")],
|
|
@@ -32221,7 +33021,7 @@ function updateFeatureDocs(featureType, featureName, targetDir, issueField, owne
|
|
|
32221
33021
|
parentField,
|
|
32222
33022
|
statusField,
|
|
32223
33023
|
versionField,
|
|
32224
|
-
|
|
33024
|
+
fs10,
|
|
32225
33025
|
[]
|
|
32226
33026
|
);
|
|
32227
33027
|
filesToOpen.push(spec, plan);
|
|
@@ -32236,7 +33036,7 @@ function updateFeatureDocs(featureType, featureName, targetDir, issueField, owne
|
|
|
32236
33036
|
parentField,
|
|
32237
33037
|
statusField,
|
|
32238
33038
|
versionField,
|
|
32239
|
-
|
|
33039
|
+
fs10,
|
|
32240
33040
|
[]
|
|
32241
33041
|
);
|
|
32242
33042
|
filesToOpen.push(epic);
|
|
@@ -32298,11 +33098,11 @@ ${get("bug_logs")}`);
|
|
|
32298
33098
|
parentField,
|
|
32299
33099
|
statusField,
|
|
32300
33100
|
versionField,
|
|
32301
|
-
|
|
33101
|
+
fs10,
|
|
32302
33102
|
updates
|
|
32303
33103
|
);
|
|
32304
33104
|
if (bugValidation) {
|
|
32305
|
-
let specContent =
|
|
33105
|
+
let specContent = fs10.readText(spec);
|
|
32306
33106
|
const updateTestStrategy = (body) => prependToSectionBody(body, `Seeded from issue:
|
|
32307
33107
|
|
|
32308
33108
|
${bugValidation}`);
|
|
@@ -32311,7 +33111,7 @@ ${bugValidation}`);
|
|
|
32311
33111
|
"Test Strategy",
|
|
32312
33112
|
updateTestStrategy
|
|
32313
33113
|
);
|
|
32314
|
-
|
|
33114
|
+
fs10.writeText(spec, specContent);
|
|
32315
33115
|
}
|
|
32316
33116
|
applyHeaderAndSections(
|
|
32317
33117
|
plan,
|
|
@@ -32322,7 +33122,7 @@ ${bugValidation}`);
|
|
|
32322
33122
|
parentField,
|
|
32323
33123
|
statusField,
|
|
32324
33124
|
versionField,
|
|
32325
|
-
|
|
33125
|
+
fs10,
|
|
32326
33126
|
[]
|
|
32327
33127
|
);
|
|
32328
33128
|
filesToOpen.push(spec, plan);
|
|
@@ -32393,6 +33193,7 @@ function createActiveFolder(options) {
|
|
|
32393
33193
|
filesystem
|
|
32394
33194
|
);
|
|
32395
33195
|
const potentialContent = potentialFile ? filesystem.readText(potentialFile) : "";
|
|
33196
|
+
const retainsPotentialSource = potentialFile !== null && isPromotedPotentialSource(potentialFile, workspacePath);
|
|
32396
33197
|
const selectedWorkMode = normalizeRequestedWorkMode(workMode, featureType);
|
|
32397
33198
|
const [useMinorAudit, fallbackReason] = shouldUseMinorAuditMode(
|
|
32398
33199
|
selectedWorkMode,
|
|
@@ -32480,7 +33281,11 @@ function createActiveFolder(options) {
|
|
|
32480
33281
|
if (useMinorAudit) {
|
|
32481
33282
|
if (potentialFile) {
|
|
32482
33283
|
potentialIssuePath = joinPosix13(targetDir, "issue.md");
|
|
32483
|
-
|
|
33284
|
+
if (retainsPotentialSource) {
|
|
33285
|
+
filesystem.copyFile(potentialFile, potentialIssuePath);
|
|
33286
|
+
} else {
|
|
33287
|
+
filesystem.move(potentialFile, potentialIssuePath);
|
|
33288
|
+
}
|
|
32484
33289
|
const movedContent = filesystem.readText(potentialIssuePath);
|
|
32485
33290
|
filesystem.writeText(
|
|
32486
33291
|
potentialIssuePath,
|
|
@@ -32536,17 +33341,25 @@ function createActiveFolder(options) {
|
|
|
32536
33341
|
if (potentialFile) {
|
|
32537
33342
|
if (useMinorAudit) {
|
|
32538
33343
|
if (potentialIssuePath !== null) {
|
|
32539
|
-
emit(
|
|
33344
|
+
emit(
|
|
33345
|
+
retainsPotentialSource ? `Copied potential file to ${potentialIssuePath}` : `Moved potential file to ${potentialIssuePath}`
|
|
33346
|
+
);
|
|
32540
33347
|
}
|
|
32541
33348
|
} else {
|
|
32542
33349
|
potentialIssuePath = joinPosix13(targetDir, "issue.md");
|
|
32543
|
-
|
|
33350
|
+
if (retainsPotentialSource) {
|
|
33351
|
+
filesystem.copyFile(potentialFile, potentialIssuePath);
|
|
33352
|
+
} else {
|
|
33353
|
+
filesystem.move(potentialFile, potentialIssuePath);
|
|
33354
|
+
}
|
|
32544
33355
|
const movedContent = filesystem.readText(potentialIssuePath);
|
|
32545
33356
|
filesystem.writeText(
|
|
32546
33357
|
potentialIssuePath,
|
|
32547
33358
|
upsertWorkModeMarker(movedContent, selectedWorkMode)
|
|
32548
33359
|
);
|
|
32549
|
-
emit(
|
|
33360
|
+
emit(
|
|
33361
|
+
retainsPotentialSource ? `Copied potential file to ${potentialIssuePath}` : `Moved potential file to ${potentialIssuePath}`
|
|
33362
|
+
);
|
|
32550
33363
|
}
|
|
32551
33364
|
}
|
|
32552
33365
|
if (potentialFile) {
|
|
@@ -32585,6 +33398,12 @@ function isRelativeTo(child, root) {
|
|
|
32585
33398
|
const normalizedRoot = toPosixPath2(root);
|
|
32586
33399
|
return normalizedChild === normalizedRoot || normalizedChild.startsWith(`${normalizedRoot}/`);
|
|
32587
33400
|
}
|
|
33401
|
+
function isPromotedPotentialSource(potentialPath, workspacePath) {
|
|
33402
|
+
return isRelativeTo(
|
|
33403
|
+
potentialPath,
|
|
33404
|
+
joinPosix13(workspacePath, "docs/features/potential/promoted")
|
|
33405
|
+
);
|
|
33406
|
+
}
|
|
32588
33407
|
function posixBaseName(path11) {
|
|
32589
33408
|
const normalized = toPosixPath2(path11).replace(/\/+$/, "");
|
|
32590
33409
|
const slash = normalized.lastIndexOf("/");
|
|
@@ -32597,7 +33416,15 @@ function posixStem2(path11) {
|
|
|
32597
33416
|
}
|
|
32598
33417
|
|
|
32599
33418
|
// ../../extensions/drm-copilot/src/lib/new-active-feature-folder/new-active-feature-folder-service-call.ts
|
|
33419
|
+
function requireReportedPathExists(fileSystem, path11) {
|
|
33420
|
+
if (!fileSystem.exists(path11)) {
|
|
33421
|
+
throw new Error(
|
|
33422
|
+
`new_active_feature_folder reported a path that does not exist: ${path11}`
|
|
33423
|
+
);
|
|
33424
|
+
}
|
|
33425
|
+
}
|
|
32600
33426
|
function newActiveFeatureFolderServiceCall(input) {
|
|
33427
|
+
const fileSystem = input.fileSystem ?? new RealFolderFileSystem();
|
|
32601
33428
|
const result = createActiveFolder({
|
|
32602
33429
|
featureName: input.featureName,
|
|
32603
33430
|
featureType: input.type,
|
|
@@ -32605,13 +33432,17 @@ function newActiveFeatureFolderServiceCall(input) {
|
|
|
32605
33432
|
workMode: input.workMode,
|
|
32606
33433
|
workspace: input.workspaceRoot,
|
|
32607
33434
|
templateRoot: input.templateRoot,
|
|
32608
|
-
fs:
|
|
33435
|
+
fs: fileSystem,
|
|
32609
33436
|
// Route the guarded gh issue fetch through the injected F1 runner.
|
|
32610
33437
|
issueFetcher: (issueNumber) => defaultIssueFetcher(issueNumber, input.runner),
|
|
32611
33438
|
// No-op launcher: the MCP/non-interactive path must never open an editor.
|
|
32612
33439
|
codeLauncher: () => false,
|
|
32613
33440
|
...input.log === void 0 ? {} : { emit: input.log }
|
|
32614
33441
|
});
|
|
33442
|
+
requireReportedPathExists(fileSystem, result.target);
|
|
33443
|
+
if (result.potentialIssuePath !== null) {
|
|
33444
|
+
requireReportedPathExists(fileSystem, result.potentialIssuePath);
|
|
33445
|
+
}
|
|
32615
33446
|
return {
|
|
32616
33447
|
tool: "new_active_feature_folder",
|
|
32617
33448
|
workspaceRoot: input.workspaceRoot,
|
|
@@ -33388,7 +34219,7 @@ function readPackageVersion(extensionRoot) {
|
|
|
33388
34219
|
const packageJsonPath = path10.join(extensionRoot, "package.json");
|
|
33389
34220
|
try {
|
|
33390
34221
|
const packageJson = JSON.parse(
|
|
33391
|
-
|
|
34222
|
+
fs9.readFileSync(packageJsonPath, "utf-8")
|
|
33392
34223
|
);
|
|
33393
34224
|
return packageJson.version ?? "0.0.1";
|
|
33394
34225
|
} catch {
|