@danmoisan/drm-copilot-mcp 1.1.16 → 1.1.18
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 +1139 -133
- package/package.json +4 -3
- package/resources/claude-customizations/.claude/agents/feature-review.md +10 -1
- package/resources/claude-customizations/.claude/agents/orchestrator.md +16 -3
- package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +18 -6
- package/resources/claude-customizations/.claude/agents/python-typed-engineer.md +3 -3
- package/resources/claude-customizations/.claude/hooks/{enforce-powershell-batch-budget-route.ps1 → enforce-batch-budget-route.ps1} +12 -10
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-resolution.ps1 +221 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +42 -66
- package/resources/claude-customizations/.claude/hooks/enforce-epic-wave-barrier.ps1 +58 -10
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate-resolution.ps1 +144 -0
- package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +36 -47
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +179 -27
- package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +21 -38
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-abandon-gate.ps1 +4 -4
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-cohort-barrier.ps1 +58 -10
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-drift-gate.ps1 +59 -9
- package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +114 -37
- package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +3 -3
- package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +99 -64
- package/resources/claude-customizations/.claude/lib/bash/abandon-parallel-item.sh +176 -0
- package/resources/claude-customizations/.claude/lib/bash/parallel-lane-assertion.sh +4 -2
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusConflict.psm1 +193 -14
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusGlob.psm1 +51 -28
- package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusScheduling.psm1 +5 -8
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorState.psm1 +6 -13
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1 +375 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateReceipts.psm1 +22 -15
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRemediationAccounting.psm1 +337 -0
- package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRoutingContract.psm1 +9 -1
- package/resources/claude-customizations/.claude/lib/parallel-drift/Invoke-ParallelDriftDetection.ps1 +336 -0
- package/resources/claude-customizations/.claude/lib/parallel-drift/ParallelDrift.psm1 +467 -0
- package/resources/claude-customizations/.claude/lib/parallel-drift/ParallelDriftHalt.psm1 +388 -0
- package/resources/claude-customizations/.claude/lib/worktree-resolution/EpicScopeResolution.psm1 +53 -32
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeItemResolution.psm1 +19 -4
- package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunResolution.psm1 +497 -0
- package/resources/claude-customizations/.claude/rules/orchestrator-state.md +119 -3
- package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +21 -0
- package/resources/claude-customizations/.claude/rules/quality-tiers.md +1 -1
- package/resources/claude-customizations/.claude/skills/acceptance-criteria-tracking/SKILL.md +8 -0
- package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +2 -0
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +11 -3
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup-worktrees.sh +11 -2
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_enumerate_lib.sh +169 -5
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_lib.sh +1 -1
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_report_records_lib.sh +6 -43
- package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_scan_helper.sh +4 -15
- package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +15 -6
- package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +4 -0
- package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +10 -0
- package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +3 -1
- package/resources/claude-customizations/.claude/skills/invoke-csharp-engineer/SKILL.md +4 -0
- package/resources/claude-customizations/.claude/skills/invoke-powershell-engineer/SKILL.md +4 -0
- package/resources/claude-customizations/.claude/skills/invoke-python-engineer/SKILL.md +6 -3
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +33 -13
- package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +50 -21
- package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +10 -10
- package/resources/claude-customizations/.claude/skills/python-change-budget-router/SKILL.md +11 -35
- package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +5 -1
- package/resources/claude-customizations/pack-manifests/core.json +10 -0
- package/resources/claude-customizations/pack-manifests/powershell.json +0 -1
- package/resources/codex-and-agents-customizations/.agents/skills/acceptance-criteria-tracking/SKILL.md +8 -0
- package/resources/codex-and-agents-customizations/.agents/skills/epic-orchestrate/SKILL.md +5 -3
- package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +4 -0
- package/resources/codex-and-agents-customizations/.agents/skills/feature-promotion-lifecycle/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review/SKILL.md +30 -6
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +3 -1
- package/resources/codex-and-agents-customizations/.agents/skills/invoke-powershell-engineer/SKILL.md +0 -1
- package/resources/codex-and-agents-customizations/.agents/skills/invoke-python-engineer/SKILL.md +2 -3
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +30 -7
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-state/SKILL.md +41 -2
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +18 -3
- package/resources/codex-and-agents-customizations/.agents/skills/python-change-budget-router/SKILL.md +10 -34
- package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +1 -1
- package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +2 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c1.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c2.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3-elevated.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c4.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer.toml +1 -0
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c1.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/agents/python-orchestrator.toml +2 -2
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c1.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c2.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3-elevated.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c4.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer.toml +3 -3
- package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-batch-budget-route.ps1 +139 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +4 -124
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +169 -79
- package/resources/codex-and-agents-customizations/pack-manifests/core.json +1 -0
- package/resources/customizations/.github/agents/python-orchestrator.agent.md +4 -4
- package/resources/customizations/.github/agents/python-typed-engineer.agent.md +7 -8
- package/resources/customizations/.github/prompts/orchestrate-python-work.prompt.md +3 -3
- package/resources/customizations/.github/skills/acceptance-criteria-tracking/SKILL.md +8 -0
- package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +4 -0
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +16 -1
package/out/mcp-server.js
CHANGED
|
@@ -1146,9 +1146,9 @@ var require_util = __commonJS({
|
|
|
1146
1146
|
}
|
|
1147
1147
|
}
|
|
1148
1148
|
exports2.eachItem = eachItem;
|
|
1149
|
-
function makeMergeEvaluated({ mergeNames, mergeToName, mergeValues:
|
|
1149
|
+
function makeMergeEvaluated({ mergeNames, mergeToName, mergeValues: mergeValues3, resultToName }) {
|
|
1150
1150
|
return (gen, from, to, toName) => {
|
|
1151
|
-
const res = to === void 0 ? from : to instanceof codegen_1.Name ? (from instanceof codegen_1.Name ? mergeNames(gen, from, to) : mergeToName(gen, from, to), to) : from instanceof codegen_1.Name ? (mergeToName(gen, to, from), from) :
|
|
1151
|
+
const res = to === void 0 ? from : to instanceof codegen_1.Name ? (from instanceof codegen_1.Name ? mergeNames(gen, from, to) : mergeToName(gen, from, to), to) : from instanceof codegen_1.Name ? (mergeToName(gen, to, from), from) : mergeValues3(from, to);
|
|
1152
1152
|
return toName === codegen_1.Name && !(res instanceof codegen_1.Name) ? resultToName(gen, res) : res;
|
|
1153
1153
|
};
|
|
1154
1154
|
}
|
|
@@ -4150,13 +4150,14 @@ var require_fast_uri = __commonJS({
|
|
|
4150
4150
|
if (!malformedIPLiteral) {
|
|
4151
4151
|
malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
|
|
4152
4152
|
}
|
|
4153
|
-
if (
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
parsed.host = reescapeHostDelimiters(host, isIP);
|
|
4158
|
-
}
|
|
4153
|
+
if (uri.indexOf("%") !== -1 && parsed.host !== void 0 && !malformedIPLiteral) {
|
|
4154
|
+
let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
|
|
4155
|
+
if (!isIP) {
|
|
4156
|
+
host = normalizePercentEncoding(host.toLowerCase());
|
|
4159
4157
|
}
|
|
4158
|
+
parsed.host = reescapeHostDelimiters(host, isIP);
|
|
4159
|
+
}
|
|
4160
|
+
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
4160
4161
|
if (parsed.path) {
|
|
4161
4162
|
parsed.path = normalizePathEncoding(parsed.path);
|
|
4162
4163
|
}
|
|
@@ -9273,13 +9274,13 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
9273
9274
|
}
|
|
9274
9275
|
return propValues;
|
|
9275
9276
|
});
|
|
9276
|
-
const
|
|
9277
|
+
const isObject16 = isObject;
|
|
9277
9278
|
const catchall = def.catchall;
|
|
9278
9279
|
let value;
|
|
9279
9280
|
inst._zod.parse = (payload, ctx) => {
|
|
9280
9281
|
value ?? (value = _normalized.value);
|
|
9281
9282
|
const input = payload.value;
|
|
9282
|
-
if (!
|
|
9283
|
+
if (!isObject16(input)) {
|
|
9283
9284
|
payload.issues.push({
|
|
9284
9285
|
expected: "object",
|
|
9285
9286
|
code: "invalid_type",
|
|
@@ -9406,7 +9407,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
9406
9407
|
return (payload, ctx) => fn(shape, payload, ctx);
|
|
9407
9408
|
};
|
|
9408
9409
|
let fastpass;
|
|
9409
|
-
const
|
|
9410
|
+
const isObject16 = isObject;
|
|
9410
9411
|
const jit = !globalConfig.jitless;
|
|
9411
9412
|
const allowsEval2 = allowsEval;
|
|
9412
9413
|
const fastEnabled = jit && allowsEval2.value;
|
|
@@ -9415,7 +9416,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
9415
9416
|
inst._zod.parse = (payload, ctx) => {
|
|
9416
9417
|
value ?? (value = _normalized.value);
|
|
9417
9418
|
const input = payload.value;
|
|
9418
|
-
if (!
|
|
9419
|
+
if (!isObject16(input)) {
|
|
9419
9420
|
payload.issues.push({
|
|
9420
9421
|
expected: "object",
|
|
9421
9422
|
code: "invalid_type",
|
|
@@ -19984,6 +19985,237 @@ var BlastRadiusDeriveFileSystem = class {
|
|
|
19984
19985
|
}
|
|
19985
19986
|
};
|
|
19986
19987
|
|
|
19988
|
+
// ../../extensions/drm-copilot/src/lib/push-down/claude-blast-radius-overlay.ts
|
|
19989
|
+
var BLAST_RADIUS_OVERLAY_RELATIVE_PATH = "config/blast-radius.local.json";
|
|
19990
|
+
var STRING_LIST_KEYS = /* @__PURE__ */ new Set([
|
|
19991
|
+
"shared_surfaces",
|
|
19992
|
+
"shared_surface_globs",
|
|
19993
|
+
"mandate_reads",
|
|
19994
|
+
"mergeable_paths",
|
|
19995
|
+
"path_roots"
|
|
19996
|
+
]);
|
|
19997
|
+
var MODULES_KEY = "modules";
|
|
19998
|
+
var VERSION_KEY = "version";
|
|
19999
|
+
var BlastRadiusOverlayError = class extends Error {
|
|
20000
|
+
/** Relative path of the document that could not be composed. */
|
|
20001
|
+
path;
|
|
20002
|
+
/**
|
|
20003
|
+
* @param path Relative path of the offending document.
|
|
20004
|
+
* @param detail Reason appended to the message.
|
|
20005
|
+
*/
|
|
20006
|
+
constructor(path16, detail) {
|
|
20007
|
+
super(
|
|
20008
|
+
`Blast-radius overlay ${path16} was not applied; ${BLAST_RADIUS_RELATIVE_PATH} was not written: ${detail}`
|
|
20009
|
+
);
|
|
20010
|
+
this.name = "BlastRadiusOverlayError";
|
|
20011
|
+
this.path = path16;
|
|
20012
|
+
}
|
|
20013
|
+
};
|
|
20014
|
+
function isJsonObject(value) {
|
|
20015
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
20016
|
+
}
|
|
20017
|
+
function isStringList(value) {
|
|
20018
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
20019
|
+
}
|
|
20020
|
+
function parseObject(text2, path16) {
|
|
20021
|
+
let parsed;
|
|
20022
|
+
try {
|
|
20023
|
+
parsed = JSON.parse(text2);
|
|
20024
|
+
} catch (error2) {
|
|
20025
|
+
const detail = error2 instanceof Error ? error2.message : String(error2);
|
|
20026
|
+
throw new BlastRadiusOverlayError(path16, `not valid JSON (${detail})`);
|
|
20027
|
+
}
|
|
20028
|
+
if (!isJsonObject(parsed)) {
|
|
20029
|
+
throw new BlastRadiusOverlayError(
|
|
20030
|
+
path16,
|
|
20031
|
+
"document root is not a JSON object"
|
|
20032
|
+
);
|
|
20033
|
+
}
|
|
20034
|
+
return parsed;
|
|
20035
|
+
}
|
|
20036
|
+
function unionStrings(base, overlay) {
|
|
20037
|
+
const composed = [...base];
|
|
20038
|
+
const seen = new Set(base.filter((item) => typeof item === "string"));
|
|
20039
|
+
for (const item of overlay) {
|
|
20040
|
+
if (!seen.has(item)) {
|
|
20041
|
+
seen.add(item);
|
|
20042
|
+
composed.push(item);
|
|
20043
|
+
}
|
|
20044
|
+
}
|
|
20045
|
+
return composed;
|
|
20046
|
+
}
|
|
20047
|
+
function composeStringList(key, base, overlay, overlayPath) {
|
|
20048
|
+
if (!isStringList(overlay)) {
|
|
20049
|
+
throw new BlastRadiusOverlayError(
|
|
20050
|
+
overlayPath,
|
|
20051
|
+
`key "${key}" must be a list of strings`
|
|
20052
|
+
);
|
|
20053
|
+
}
|
|
20054
|
+
return unionStrings(Array.isArray(base) ? base : [], overlay);
|
|
20055
|
+
}
|
|
20056
|
+
function composeModules(base, overlay, overlayPath) {
|
|
20057
|
+
if (!isJsonObject(overlay) || !Object.values(overlay).every((globs) => isStringList(globs))) {
|
|
20058
|
+
throw new BlastRadiusOverlayError(
|
|
20059
|
+
overlayPath,
|
|
20060
|
+
`key "${MODULES_KEY}" must map module names to lists of strings`
|
|
20061
|
+
);
|
|
20062
|
+
}
|
|
20063
|
+
const merged = { ...isJsonObject(base) ? base : {} };
|
|
20064
|
+
for (const [name, globs] of Object.entries(overlay)) {
|
|
20065
|
+
merged[name] = globs;
|
|
20066
|
+
}
|
|
20067
|
+
const composed = {};
|
|
20068
|
+
for (const name of Object.keys(merged).sort(compareOrdinal)) {
|
|
20069
|
+
const globs = merged[name] ?? [];
|
|
20070
|
+
composed[name] = globs;
|
|
20071
|
+
for (const glob of Array.isArray(globs) ? globs : []) {
|
|
20072
|
+
if (typeof glob === "string" && FORBIDDEN_GLOBS.includes(glob)) {
|
|
20073
|
+
throw new BlastRadiusGuardError(name, glob);
|
|
20074
|
+
}
|
|
20075
|
+
}
|
|
20076
|
+
}
|
|
20077
|
+
return composed;
|
|
20078
|
+
}
|
|
20079
|
+
function mergeValues2(base, overlay, dottedKey, overlayPath) {
|
|
20080
|
+
if (isJsonObject(base) && isJsonObject(overlay)) {
|
|
20081
|
+
const merged = {};
|
|
20082
|
+
for (const [key, value] of Object.entries(base)) {
|
|
20083
|
+
const overlayValue = overlay[key];
|
|
20084
|
+
merged[key] = overlayValue === void 0 ? value : mergeValues2(
|
|
20085
|
+
value,
|
|
20086
|
+
overlayValue,
|
|
20087
|
+
`${dottedKey}.${key}`,
|
|
20088
|
+
overlayPath
|
|
20089
|
+
);
|
|
20090
|
+
}
|
|
20091
|
+
for (const [key, value] of Object.entries(overlay)) {
|
|
20092
|
+
if (!(key in merged)) {
|
|
20093
|
+
merged[key] = value;
|
|
20094
|
+
}
|
|
20095
|
+
}
|
|
20096
|
+
return merged;
|
|
20097
|
+
}
|
|
20098
|
+
if (Array.isArray(base) && Array.isArray(overlay)) {
|
|
20099
|
+
if (!isStringList(overlay)) {
|
|
20100
|
+
throw new BlastRadiusOverlayError(
|
|
20101
|
+
overlayPath,
|
|
20102
|
+
`key "${dottedKey}" must be a list of strings`
|
|
20103
|
+
);
|
|
20104
|
+
}
|
|
20105
|
+
return unionStrings(base, overlay);
|
|
20106
|
+
}
|
|
20107
|
+
return overlay;
|
|
20108
|
+
}
|
|
20109
|
+
function composeKey(key, base, overlay, overlayPath) {
|
|
20110
|
+
if (STRING_LIST_KEYS.has(key)) {
|
|
20111
|
+
return composeStringList(key, base, overlay, overlayPath);
|
|
20112
|
+
}
|
|
20113
|
+
if (key === MODULES_KEY) {
|
|
20114
|
+
return composeModules(base, overlay, overlayPath);
|
|
20115
|
+
}
|
|
20116
|
+
return base === void 0 ? overlay : mergeValues2(base, overlay, key, overlayPath);
|
|
20117
|
+
}
|
|
20118
|
+
function composeBlastRadiusOverlay(baseText, overlayText, overlayPath) {
|
|
20119
|
+
if (overlayText === null) {
|
|
20120
|
+
return baseText;
|
|
20121
|
+
}
|
|
20122
|
+
const overlay = parseObject(overlayText, overlayPath);
|
|
20123
|
+
const base = parseObject(baseText, BLAST_RADIUS_RELATIVE_PATH);
|
|
20124
|
+
if (VERSION_KEY in overlay && overlay[VERSION_KEY] !== base[VERSION_KEY]) {
|
|
20125
|
+
throw new BlastRadiusOverlayError(
|
|
20126
|
+
overlayPath,
|
|
20127
|
+
`key "${VERSION_KEY}" does not match the base version`
|
|
20128
|
+
);
|
|
20129
|
+
}
|
|
20130
|
+
const composed = {};
|
|
20131
|
+
for (const [key, value] of Object.entries(base)) {
|
|
20132
|
+
const overlayValue = overlay[key];
|
|
20133
|
+
composed[key] = key === VERSION_KEY || overlayValue === void 0 ? value : composeKey(key, value, overlayValue, overlayPath);
|
|
20134
|
+
}
|
|
20135
|
+
for (const [key, value] of Object.entries(overlay)) {
|
|
20136
|
+
if (!(key in composed)) {
|
|
20137
|
+
composed[key] = composeKey(key, void 0, value, overlayPath);
|
|
20138
|
+
}
|
|
20139
|
+
}
|
|
20140
|
+
return `${JSON.stringify(composed, null, 2)}
|
|
20141
|
+
`;
|
|
20142
|
+
}
|
|
20143
|
+
function normalizePosix6(value) {
|
|
20144
|
+
return value.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
20145
|
+
}
|
|
20146
|
+
function relativeToPosix6(path16, root) {
|
|
20147
|
+
const normalizedPath = normalizePosix6(path16);
|
|
20148
|
+
const normalizedRoot = normalizePosix6(root);
|
|
20149
|
+
if (normalizedPath === normalizedRoot) {
|
|
20150
|
+
return "";
|
|
20151
|
+
}
|
|
20152
|
+
const prefix = `${normalizedRoot}/`;
|
|
20153
|
+
return normalizedPath.startsWith(prefix) ? normalizedPath.slice(prefix.length) : null;
|
|
20154
|
+
}
|
|
20155
|
+
var BlastRadiusOverlayFileSystem = class {
|
|
20156
|
+
inner;
|
|
20157
|
+
destinationRoot;
|
|
20158
|
+
overlayRelativePath;
|
|
20159
|
+
targetRelativePath;
|
|
20160
|
+
/**
|
|
20161
|
+
* @param inner The wrapped adapter performing real I/O.
|
|
20162
|
+
* @param destinationRoot Destination workspace root (POSIX path).
|
|
20163
|
+
* @param overlayRelativePath Destination-relative overlay path.
|
|
20164
|
+
* @param targetRelativePath Destination-relative path the overlay composes
|
|
20165
|
+
* onto.
|
|
20166
|
+
*/
|
|
20167
|
+
constructor(inner, destinationRoot, overlayRelativePath = BLAST_RADIUS_OVERLAY_RELATIVE_PATH, targetRelativePath = BLAST_RADIUS_RELATIVE_PATH) {
|
|
20168
|
+
this.inner = inner;
|
|
20169
|
+
this.destinationRoot = normalizePosix6(destinationRoot);
|
|
20170
|
+
this.overlayRelativePath = overlayRelativePath;
|
|
20171
|
+
this.targetRelativePath = targetRelativePath;
|
|
20172
|
+
}
|
|
20173
|
+
/** @inheritdoc */
|
|
20174
|
+
listFiles(root) {
|
|
20175
|
+
return this.inner.listFiles(root);
|
|
20176
|
+
}
|
|
20177
|
+
/** @inheritdoc */
|
|
20178
|
+
isDir(path16) {
|
|
20179
|
+
return this.inner.isDir(path16);
|
|
20180
|
+
}
|
|
20181
|
+
/** @inheritdoc */
|
|
20182
|
+
isFile(path16) {
|
|
20183
|
+
return this.inner.isFile(path16);
|
|
20184
|
+
}
|
|
20185
|
+
/** @inheritdoc */
|
|
20186
|
+
readTextFile(path16) {
|
|
20187
|
+
return this.inner.readTextFile(path16);
|
|
20188
|
+
}
|
|
20189
|
+
/** @inheritdoc */
|
|
20190
|
+
ensureDir(path16) {
|
|
20191
|
+
this.inner.ensureDir(path16);
|
|
20192
|
+
}
|
|
20193
|
+
/**
|
|
20194
|
+
* Write a file, composing the destination overlay onto the target path.
|
|
20195
|
+
*
|
|
20196
|
+
* @param path Absolute destination POSIX path.
|
|
20197
|
+
* @param content Content the layers above want to publish.
|
|
20198
|
+
* @throws BlastRadiusOverlayError When the overlay cannot be composed; the
|
|
20199
|
+
* destination target keeps its prior bytes.
|
|
20200
|
+
* @throws BlastRadiusGuardError When a composed module carries a forbidden
|
|
20201
|
+
* glob; the destination target keeps its prior bytes.
|
|
20202
|
+
*/
|
|
20203
|
+
writeTextFile(path16, content) {
|
|
20204
|
+
if (relativeToPosix6(path16, this.destinationRoot) !== this.targetRelativePath) {
|
|
20205
|
+
this.inner.writeTextFile(path16, content);
|
|
20206
|
+
return;
|
|
20207
|
+
}
|
|
20208
|
+
const overlayPath = `${this.destinationRoot}/${this.overlayRelativePath}`;
|
|
20209
|
+
const overlayText = this.inner.isFile(overlayPath) ? this.inner.readTextFile(overlayPath) : null;
|
|
20210
|
+
const composed = composeBlastRadiusOverlay(
|
|
20211
|
+
content,
|
|
20212
|
+
overlayText,
|
|
20213
|
+
this.overlayRelativePath
|
|
20214
|
+
);
|
|
20215
|
+
this.inner.writeTextFile(path16, composed);
|
|
20216
|
+
}
|
|
20217
|
+
};
|
|
20218
|
+
|
|
19987
20219
|
// ../../extensions/drm-copilot/src/lib/push-down/claude-gitignore-merge.ts
|
|
19988
20220
|
var CLAUDE_GITIGNORE_RELATIVE_PATH = ".gitignore";
|
|
19989
20221
|
var CLAUDE_GITIGNORE_BEGIN_SENTINEL = "# BEGIN drm-copilot managed ignores";
|
|
@@ -20043,12 +20275,363 @@ function toDocument(lines) {
|
|
|
20043
20275
|
return `${lines.join(LINE_SEPARATOR)}${LINE_SEPARATOR}`;
|
|
20044
20276
|
}
|
|
20045
20277
|
|
|
20278
|
+
// ../../extensions/drm-copilot/src/lib/push-down/claude-exclusion-manifest.ts
|
|
20279
|
+
var EXCLUSION_MANIFEST_RELATIVE_PATH = ".push-down-exclusions";
|
|
20280
|
+
var ExclusionManifestError = class extends Error {
|
|
20281
|
+
/** Destination-relative manifest path. */
|
|
20282
|
+
path;
|
|
20283
|
+
/** 1-based offending line, or `undefined` when the whole file is at fault. */
|
|
20284
|
+
line;
|
|
20285
|
+
/**
|
|
20286
|
+
* @param path Destination-relative manifest path.
|
|
20287
|
+
* @param line Offending line, or `undefined` for a whole-file condition.
|
|
20288
|
+
* @param reason Human-readable reason.
|
|
20289
|
+
*/
|
|
20290
|
+
constructor(path16, line, reason) {
|
|
20291
|
+
const location = line === void 0 ? path16 : `${path16} line ${String(line)}`;
|
|
20292
|
+
super(`Malformed push-down exclusion manifest ${location}: ${reason}`);
|
|
20293
|
+
this.name = "ExclusionManifestError";
|
|
20294
|
+
this.path = path16;
|
|
20295
|
+
this.line = line;
|
|
20296
|
+
}
|
|
20297
|
+
};
|
|
20298
|
+
var BYTE_ORDER_MARK = "\uFEFF";
|
|
20299
|
+
var REPLACEMENT_CHARACTER = "\uFFFD";
|
|
20300
|
+
var LINE_SPLIT = /\r?\n/;
|
|
20301
|
+
var REPEATED_SLASH = /\/{2,}/g;
|
|
20302
|
+
var DRIVE_PREFIX = /^[A-Za-z]:/;
|
|
20303
|
+
function hasWildcard(normalized) {
|
|
20304
|
+
return normalized.includes("*") || normalized.includes("?");
|
|
20305
|
+
}
|
|
20306
|
+
function escapeRegexCharacter(character) {
|
|
20307
|
+
return /[\\^$.*+?()[\]{}|/-]/.test(character) ? `\\${character}` : character;
|
|
20308
|
+
}
|
|
20309
|
+
function globToRegexText(pattern) {
|
|
20310
|
+
const parts = [];
|
|
20311
|
+
let index = 0;
|
|
20312
|
+
while (index < pattern.length) {
|
|
20313
|
+
if (pattern.startsWith("**", index)) {
|
|
20314
|
+
parts.push(".*");
|
|
20315
|
+
index += 2;
|
|
20316
|
+
continue;
|
|
20317
|
+
}
|
|
20318
|
+
const character = pattern.charAt(index);
|
|
20319
|
+
if (character === "*") {
|
|
20320
|
+
parts.push("[^/]*");
|
|
20321
|
+
} else if (character === "?") {
|
|
20322
|
+
parts.push("[^/]");
|
|
20323
|
+
} else {
|
|
20324
|
+
parts.push(escapeRegexCharacter(character));
|
|
20325
|
+
}
|
|
20326
|
+
index += 1;
|
|
20327
|
+
}
|
|
20328
|
+
return parts.join("");
|
|
20329
|
+
}
|
|
20330
|
+
function matchesGlob(pattern, candidate) {
|
|
20331
|
+
return new RegExp(`^(?:${globToRegexText(pattern)})$`).test(candidate);
|
|
20332
|
+
}
|
|
20333
|
+
function normalizeExclusionEntry(raw) {
|
|
20334
|
+
let text2 = raw.trim().replace(/\\/g, "/");
|
|
20335
|
+
if (text2.startsWith("./")) {
|
|
20336
|
+
text2 = text2.slice(2);
|
|
20337
|
+
}
|
|
20338
|
+
return text2.replace(REPEATED_SLASH, "/");
|
|
20339
|
+
}
|
|
20340
|
+
function malformedReason(normalized) {
|
|
20341
|
+
const checks = [
|
|
20342
|
+
[normalized === "", "entry is empty after normalization"],
|
|
20343
|
+
[
|
|
20344
|
+
normalized.startsWith("/") || DRIVE_PREFIX.test(normalized),
|
|
20345
|
+
"entry is an absolute path"
|
|
20346
|
+
],
|
|
20347
|
+
[normalized.split("/").includes(".."), "entry contains a '..' segment"],
|
|
20348
|
+
[normalized.startsWith("!"), "negation entries are not supported"],
|
|
20349
|
+
[
|
|
20350
|
+
normalized.includes("[") || normalized.includes("]"),
|
|
20351
|
+
"character classes are not supported"
|
|
20352
|
+
],
|
|
20353
|
+
[
|
|
20354
|
+
hasWildcard(normalized) && normalized.endsWith("/"),
|
|
20355
|
+
"a wildcard entry must not end with '/'"
|
|
20356
|
+
],
|
|
20357
|
+
[normalized.includes(REPLACEMENT_CHARACTER), "text is not valid UTF-8"]
|
|
20358
|
+
];
|
|
20359
|
+
const failed = checks.find(([isFailed]) => isFailed);
|
|
20360
|
+
return failed === void 0 ? void 0 : failed[1];
|
|
20361
|
+
}
|
|
20362
|
+
function classify(normalized) {
|
|
20363
|
+
if (hasWildcard(normalized)) {
|
|
20364
|
+
return "glob";
|
|
20365
|
+
}
|
|
20366
|
+
return normalized.endsWith("/") ? "directory" : "exact";
|
|
20367
|
+
}
|
|
20368
|
+
function parseExclusionManifest(text2, path16) {
|
|
20369
|
+
const body = text2.startsWith(BYTE_ORDER_MARK) ? text2.slice(BYTE_ORDER_MARK.length) : text2;
|
|
20370
|
+
const entries = [];
|
|
20371
|
+
body.split(LINE_SPLIT).forEach((raw, offset) => {
|
|
20372
|
+
const line = offset + 1;
|
|
20373
|
+
const stripped = raw.trim();
|
|
20374
|
+
if (stripped === "" || stripped.startsWith("#")) {
|
|
20375
|
+
return;
|
|
20376
|
+
}
|
|
20377
|
+
const normalized = normalizeExclusionEntry(raw);
|
|
20378
|
+
const reason = malformedReason(normalized);
|
|
20379
|
+
if (reason !== void 0) {
|
|
20380
|
+
throw new ExclusionManifestError(path16, line, reason);
|
|
20381
|
+
}
|
|
20382
|
+
entries.push({ raw, normalized, kind: classify(normalized), line });
|
|
20383
|
+
});
|
|
20384
|
+
return { path: path16, entries };
|
|
20385
|
+
}
|
|
20386
|
+
function matchesExclusionEntry(entry, candidate) {
|
|
20387
|
+
if (entry.kind === "glob") {
|
|
20388
|
+
return matchesGlob(entry.normalized, candidate);
|
|
20389
|
+
}
|
|
20390
|
+
const base = entry.normalized.replace(/\/+$/, "");
|
|
20391
|
+
return candidate === base || candidate.startsWith(`${base}/`);
|
|
20392
|
+
}
|
|
20393
|
+
function planExclusions(payloadRelativePaths, manifest, destinationExists) {
|
|
20394
|
+
const kept = [];
|
|
20395
|
+
const skipped = [];
|
|
20396
|
+
for (const relativePath2 of payloadRelativePaths) {
|
|
20397
|
+
const entry = manifest.entries.find(
|
|
20398
|
+
(candidate) => matchesExclusionEntry(candidate, relativePath2)
|
|
20399
|
+
);
|
|
20400
|
+
if (entry === void 0) {
|
|
20401
|
+
kept.push(relativePath2);
|
|
20402
|
+
continue;
|
|
20403
|
+
}
|
|
20404
|
+
skipped.push({
|
|
20405
|
+
relativePath: relativePath2,
|
|
20406
|
+
entry: entry.normalized,
|
|
20407
|
+
line: entry.line,
|
|
20408
|
+
destinationStatus: destinationExists(relativePath2) ? "present" : "absent"
|
|
20409
|
+
});
|
|
20410
|
+
}
|
|
20411
|
+
const claimed = new Set(
|
|
20412
|
+
skipped.map((skip) => `${String(skip.line)}\0${skip.entry}`)
|
|
20413
|
+
);
|
|
20414
|
+
const unmatchedEntries = manifest.entries.filter(
|
|
20415
|
+
(entry) => !claimed.has(`${String(entry.line)}\0${entry.normalized}`)
|
|
20416
|
+
);
|
|
20417
|
+
return { kept, skipped, unmatchedEntries };
|
|
20418
|
+
}
|
|
20419
|
+
function assertManifestPathIsRootLevel(relativePath2, rootFolders) {
|
|
20420
|
+
if (relativePath2.includes("/")) {
|
|
20421
|
+
throw new Error(
|
|
20422
|
+
`Exclusion manifest path must be root-level: ${relativePath2}`
|
|
20423
|
+
);
|
|
20424
|
+
}
|
|
20425
|
+
const root = rootFolders.find((name) => relativePath2.startsWith(name));
|
|
20426
|
+
if (root !== void 0) {
|
|
20427
|
+
throw new Error(
|
|
20428
|
+
`Exclusion manifest path must not begin with published root ${root}: ${relativePath2}`
|
|
20429
|
+
);
|
|
20430
|
+
}
|
|
20431
|
+
}
|
|
20432
|
+
|
|
20433
|
+
// ../../extensions/drm-copilot/src/lib/push-down/claude-exclusion-filter.ts
|
|
20434
|
+
var EXCLUSION_CONFLICT_LINE_PREFIX = "push-down exclusion conflict:";
|
|
20435
|
+
var DEFAULT_ARTIFACT_DIRECTORY = "artifacts/claude-customizations";
|
|
20436
|
+
var ExclusionViolationError = class extends Error {
|
|
20437
|
+
/**
|
|
20438
|
+
* @param message Description of the refused write.
|
|
20439
|
+
*/
|
|
20440
|
+
constructor(message) {
|
|
20441
|
+
super(message);
|
|
20442
|
+
this.name = "ExclusionViolationError";
|
|
20443
|
+
}
|
|
20444
|
+
};
|
|
20445
|
+
function normalizePosix7(value) {
|
|
20446
|
+
return value.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
20447
|
+
}
|
|
20448
|
+
function relativeToPosix7(path16, root) {
|
|
20449
|
+
const normalizedPath = normalizePosix7(path16);
|
|
20450
|
+
const prefix = `${normalizePosix7(root)}/`;
|
|
20451
|
+
return normalizedPath.startsWith(prefix) ? normalizedPath.slice(prefix.length) : void 0;
|
|
20452
|
+
}
|
|
20453
|
+
function findFirstMatch(manifest, candidate) {
|
|
20454
|
+
return manifest.entries.find(
|
|
20455
|
+
(entry) => matchesExclusionEntry(entry, candidate)
|
|
20456
|
+
);
|
|
20457
|
+
}
|
|
20458
|
+
var ExclusionFilterFileSystem = class {
|
|
20459
|
+
/** Skip records in enumeration order. */
|
|
20460
|
+
skipped = [];
|
|
20461
|
+
inner;
|
|
20462
|
+
sourceRoot;
|
|
20463
|
+
destinationRoot;
|
|
20464
|
+
manifest;
|
|
20465
|
+
artifactPrefix;
|
|
20466
|
+
/**
|
|
20467
|
+
* @param inner Adapter the engine would otherwise use.
|
|
20468
|
+
* @param sourceRoot Root the engine enumerates payload files under.
|
|
20469
|
+
* @param destinationRoot Destination workspace root.
|
|
20470
|
+
* @param manifest Parsed manifest.
|
|
20471
|
+
* @param artifactDirectory Destination-relative summary-artifact directory
|
|
20472
|
+
* exempt from the write guard.
|
|
20473
|
+
*/
|
|
20474
|
+
constructor(inner, sourceRoot, destinationRoot, manifest, artifactDirectory = DEFAULT_ARTIFACT_DIRECTORY) {
|
|
20475
|
+
this.inner = inner;
|
|
20476
|
+
this.sourceRoot = normalizePosix7(sourceRoot);
|
|
20477
|
+
this.destinationRoot = normalizePosix7(destinationRoot);
|
|
20478
|
+
this.manifest = manifest;
|
|
20479
|
+
this.artifactPrefix = `${normalizePosix7(artifactDirectory)}/`;
|
|
20480
|
+
}
|
|
20481
|
+
listFiles(root) {
|
|
20482
|
+
const listed = this.inner.listFiles(root);
|
|
20483
|
+
const relativeByPath = listed.map(
|
|
20484
|
+
(path16) => [path16, relativeToPosix7(path16, this.sourceRoot)]
|
|
20485
|
+
);
|
|
20486
|
+
const candidates = relativeByPath.flatMap(
|
|
20487
|
+
([, relative2]) => relative2 === void 0 ? [] : [relative2]
|
|
20488
|
+
);
|
|
20489
|
+
const plan = planExclusions(
|
|
20490
|
+
candidates,
|
|
20491
|
+
this.manifest,
|
|
20492
|
+
(relative2) => this.inner.isFile(`${this.destinationRoot}/${relative2}`)
|
|
20493
|
+
);
|
|
20494
|
+
this.skipped.push(...plan.skipped);
|
|
20495
|
+
const kept = new Set(plan.kept);
|
|
20496
|
+
return relativeByPath.filter(([, relative2]) => relative2 === void 0 || kept.has(relative2)).map(([path16]) => path16);
|
|
20497
|
+
}
|
|
20498
|
+
isDir(path16) {
|
|
20499
|
+
return this.inner.isDir(path16);
|
|
20500
|
+
}
|
|
20501
|
+
isFile(path16) {
|
|
20502
|
+
return this.inner.isFile(path16);
|
|
20503
|
+
}
|
|
20504
|
+
readTextFile(path16) {
|
|
20505
|
+
return this.inner.readTextFile(path16);
|
|
20506
|
+
}
|
|
20507
|
+
ensureDir(path16) {
|
|
20508
|
+
this.inner.ensureDir(path16);
|
|
20509
|
+
}
|
|
20510
|
+
/**
|
|
20511
|
+
* Write through the inner adapter unless the target is excluded.
|
|
20512
|
+
*
|
|
20513
|
+
* @param path Target path.
|
|
20514
|
+
* @param content Text to write.
|
|
20515
|
+
* @throws ExclusionViolationError When the destination-relative target is
|
|
20516
|
+
* the manifest path or matches a manifest entry.
|
|
20517
|
+
*/
|
|
20518
|
+
writeTextFile(path16, content) {
|
|
20519
|
+
const relative2 = relativeToPosix7(path16, this.destinationRoot);
|
|
20520
|
+
if (relative2 !== void 0 && !relative2.startsWith(this.artifactPrefix)) {
|
|
20521
|
+
if (relative2 === EXCLUSION_MANIFEST_RELATIVE_PATH) {
|
|
20522
|
+
throw new ExclusionViolationError(
|
|
20523
|
+
`Refusing to write the push-down exclusion manifest: ${relative2}`
|
|
20524
|
+
);
|
|
20525
|
+
}
|
|
20526
|
+
const entry = findFirstMatch(this.manifest, relative2);
|
|
20527
|
+
if (entry !== void 0) {
|
|
20528
|
+
throw new ExclusionViolationError(
|
|
20529
|
+
`Refusing to write excluded path ${relative2} (entry ${entry.normalized}, line ${String(entry.line)})`
|
|
20530
|
+
);
|
|
20531
|
+
}
|
|
20532
|
+
}
|
|
20533
|
+
this.inner.writeTextFile(path16, content);
|
|
20534
|
+
}
|
|
20535
|
+
};
|
|
20536
|
+
function readExclusionManifest(fs12, destinationRoot) {
|
|
20537
|
+
const manifestPath = `${normalizePosix7(destinationRoot)}/${EXCLUSION_MANIFEST_RELATIVE_PATH}`;
|
|
20538
|
+
if (!fs12.isFile(manifestPath)) {
|
|
20539
|
+
if (fs12.isDir(manifestPath)) {
|
|
20540
|
+
throw new ExclusionManifestError(
|
|
20541
|
+
EXCLUSION_MANIFEST_RELATIVE_PATH,
|
|
20542
|
+
void 0,
|
|
20543
|
+
"path is not a regular file"
|
|
20544
|
+
);
|
|
20545
|
+
}
|
|
20546
|
+
return void 0;
|
|
20547
|
+
}
|
|
20548
|
+
return parseExclusionManifest(
|
|
20549
|
+
fs12.readTextFile(manifestPath),
|
|
20550
|
+
EXCLUSION_MANIFEST_RELATIVE_PATH
|
|
20551
|
+
);
|
|
20552
|
+
}
|
|
20553
|
+
function buildExclusionReport(manifest, skipped) {
|
|
20554
|
+
const claimed = new Set(
|
|
20555
|
+
skipped.map((skip) => `${String(skip.line)}\0${skip.entry}`)
|
|
20556
|
+
);
|
|
20557
|
+
return {
|
|
20558
|
+
manifestPath: manifest.path,
|
|
20559
|
+
entries: manifest.entries,
|
|
20560
|
+
skipped: [...skipped],
|
|
20561
|
+
unmatchedEntries: manifest.entries.filter(
|
|
20562
|
+
(entry) => !claimed.has(`${String(entry.line)}\0${entry.normalized}`)
|
|
20563
|
+
)
|
|
20564
|
+
};
|
|
20565
|
+
}
|
|
20566
|
+
function renderExclusionLines(report) {
|
|
20567
|
+
const skippedLines = report.skipped.map((skip) => {
|
|
20568
|
+
const suffix2 = `${skip.relativePath} (entry ${skip.entry}, line ${String(skip.line)})`;
|
|
20569
|
+
return skip.destinationStatus === "present" ? `${EXCLUSION_CONFLICT_LINE_PREFIX} destination file present, not overwritten: ${suffix2}` : `push-down exclusion: skipped ${suffix2}`;
|
|
20570
|
+
});
|
|
20571
|
+
const unmatchedLines = report.unmatchedEntries.map(
|
|
20572
|
+
(entry) => `push-down exclusion: entry matched no payload path: ${entry.normalized} (line ${String(entry.line)})`
|
|
20573
|
+
);
|
|
20574
|
+
return [...skippedLines, ...unmatchedLines];
|
|
20575
|
+
}
|
|
20576
|
+
function exclusionReportPayload(report) {
|
|
20577
|
+
return {
|
|
20578
|
+
conflict_count: report.skipped.filter(
|
|
20579
|
+
(skip) => skip.destinationStatus === "present"
|
|
20580
|
+
).length,
|
|
20581
|
+
entries: report.entries.map((entry) => entry.normalized),
|
|
20582
|
+
manifest_path: report.manifestPath,
|
|
20583
|
+
skipped: report.skipped.map((skip) => ({
|
|
20584
|
+
destination_status: skip.destinationStatus,
|
|
20585
|
+
entry: skip.entry,
|
|
20586
|
+
line: skip.line,
|
|
20587
|
+
relative_path: skip.relativePath
|
|
20588
|
+
})),
|
|
20589
|
+
skipped_count: report.skipped.length,
|
|
20590
|
+
unmatched_entries: report.unmatchedEntries.map((entry) => entry.normalized)
|
|
20591
|
+
};
|
|
20592
|
+
}
|
|
20593
|
+
function appendExclusionsToArtifact(fs12, artifactPath, report) {
|
|
20594
|
+
const payload = JSON.parse(fs12.readTextFile(artifactPath));
|
|
20595
|
+
if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
|
|
20596
|
+
throw new Error(`Summary artifact is not a JSON object: ${artifactPath}`);
|
|
20597
|
+
}
|
|
20598
|
+
const document = {
|
|
20599
|
+
...payload,
|
|
20600
|
+
exclusions: exclusionReportPayload(report)
|
|
20601
|
+
};
|
|
20602
|
+
fs12.writeTextFile(artifactPath, stringifySorted(document, 2));
|
|
20603
|
+
}
|
|
20604
|
+
|
|
20046
20605
|
// ../../extensions/drm-copilot/src/lib/push-down/claude-customizations.ts
|
|
20047
20606
|
var ARTIFACT_DIRECTORY4 = "artifacts/claude-customizations";
|
|
20048
20607
|
var ROOT_FOLDERS2 = [".claude", "config"];
|
|
20608
|
+
assertManifestPathIsRootLevel(EXCLUSION_MANIFEST_RELATIVE_PATH, ROOT_FOLDERS2);
|
|
20049
20609
|
var ROUTING_MERGE_RELATIVE_PATH = "config/orchestration-routing.json";
|
|
20050
20610
|
var EXCLUDED_RELATIVE_PATHS = [
|
|
20051
|
-
".claude/settings.local.json"
|
|
20611
|
+
".claude/settings.local.json",
|
|
20612
|
+
"config/blast-radius.local.json"
|
|
20613
|
+
];
|
|
20614
|
+
var DESTINATION_WRITE_DECORATORS = [
|
|
20615
|
+
{
|
|
20616
|
+
relativePath: ROUTING_MERGE_RELATIVE_PATH,
|
|
20617
|
+
wrap: (inner, destinationRoot) => new RoutingMergeFileSystem(
|
|
20618
|
+
inner,
|
|
20619
|
+
destinationRoot,
|
|
20620
|
+
ROUTING_MERGE_RELATIVE_PATH
|
|
20621
|
+
)
|
|
20622
|
+
},
|
|
20623
|
+
{
|
|
20624
|
+
relativePath: BLAST_RADIUS_RELATIVE_PATH,
|
|
20625
|
+
wrap: (inner, destinationRoot) => new BlastRadiusOverlayFileSystem(inner, destinationRoot)
|
|
20626
|
+
},
|
|
20627
|
+
{
|
|
20628
|
+
relativePath: BLAST_RADIUS_RELATIVE_PATH,
|
|
20629
|
+
wrap: (inner, destinationRoot, { listEntries }) => listEntries === void 0 ? new BlastRadiusDeriveFileSystem(inner, destinationRoot) : new BlastRadiusDeriveFileSystem(
|
|
20630
|
+
inner,
|
|
20631
|
+
destinationRoot,
|
|
20632
|
+
listEntries
|
|
20633
|
+
)
|
|
20634
|
+
}
|
|
20052
20635
|
];
|
|
20053
20636
|
var BUNDLE_ROOT_RELATIVE_DIR = "extensions/drm-copilot/resources/claude-customizations";
|
|
20054
20637
|
var PACK_MANIFEST_SUBDIR2 = "pack-manifests";
|
|
@@ -20091,23 +20674,19 @@ function pushDownCustomizations4(options) {
|
|
|
20091
20674
|
} = options;
|
|
20092
20675
|
const effectiveSource = sourceRoot ?? repoRoot;
|
|
20093
20676
|
const effectiveBundle = bundleRoot ?? joinPosix7(effectiveSource, BUNDLE_ROOT_RELATIVE_DIR);
|
|
20677
|
+
const manifest = readExclusionManifest(fs12, destinationRoot);
|
|
20094
20678
|
const publishedPaths = resolvePublishedPaths2(
|
|
20095
20679
|
packs ?? null,
|
|
20096
20680
|
effectiveBundle,
|
|
20097
20681
|
fs12
|
|
20098
20682
|
);
|
|
20099
|
-
const
|
|
20100
|
-
|
|
20101
|
-
destinationRoot,
|
|
20102
|
-
|
|
20103
|
-
);
|
|
20104
|
-
const derivingFs = listEntries === void 0 ? new BlastRadiusDeriveFileSystem(mergingFs, destinationRoot) : new BlastRadiusDeriveFileSystem(
|
|
20105
|
-
mergingFs,
|
|
20106
|
-
destinationRoot,
|
|
20107
|
-
listEntries
|
|
20683
|
+
const decoratorOptions = listEntries === void 0 ? {} : { listEntries };
|
|
20684
|
+
const decoratedFs = DESTINATION_WRITE_DECORATORS.reduce(
|
|
20685
|
+
(inner, decorator) => decorator.wrap(inner, destinationRoot, decoratorOptions),
|
|
20686
|
+
fs12
|
|
20108
20687
|
);
|
|
20109
20688
|
const excludingFs = new ExcludingFileSystem(
|
|
20110
|
-
|
|
20689
|
+
decoratedFs,
|
|
20111
20690
|
repoRoot,
|
|
20112
20691
|
EXCLUDED_RELATIVE_PATHS,
|
|
20113
20692
|
{
|
|
@@ -20119,10 +20698,17 @@ function pushDownCustomizations4(options) {
|
|
|
20119
20698
|
variantRoot: effectiveBundle
|
|
20120
20699
|
}
|
|
20121
20700
|
);
|
|
20701
|
+
const exclusionFs = manifest === void 0 ? void 0 : new ExclusionFilterFileSystem(
|
|
20702
|
+
excludingFs,
|
|
20703
|
+
effectiveSource,
|
|
20704
|
+
destinationRoot,
|
|
20705
|
+
manifest,
|
|
20706
|
+
ARTIFACT_DIRECTORY4
|
|
20707
|
+
);
|
|
20122
20708
|
const summary = pushDownCustomizations({
|
|
20123
20709
|
repoRoot,
|
|
20124
20710
|
destinationRoot,
|
|
20125
|
-
fs: excludingFs,
|
|
20711
|
+
fs: exclusionFs ?? excludingFs,
|
|
20126
20712
|
...sourceRoot === void 0 ? {} : { sourceRoot },
|
|
20127
20713
|
...artifactRoot === void 0 ? {} : { artifactRoot },
|
|
20128
20714
|
rootFolders: ROOT_FOLDERS2,
|
|
@@ -20130,19 +20716,41 @@ function pushDownCustomizations4(options) {
|
|
|
20130
20716
|
rewriteReferences: passthroughRewrite2,
|
|
20131
20717
|
...clock === void 0 ? {} : { clock }
|
|
20132
20718
|
});
|
|
20133
|
-
deliverDestinationGitignore(
|
|
20134
|
-
|
|
20719
|
+
const gitignoreSkip = deliverDestinationGitignore(
|
|
20720
|
+
fs12,
|
|
20721
|
+
destinationRoot,
|
|
20722
|
+
manifest
|
|
20723
|
+
);
|
|
20724
|
+
if (manifest === void 0 || exclusionFs === void 0) {
|
|
20725
|
+
return summary;
|
|
20726
|
+
}
|
|
20727
|
+
const skipped = gitignoreSkip === void 0 ? exclusionFs.skipped : [...exclusionFs.skipped, gitignoreSkip];
|
|
20728
|
+
const report = buildExclusionReport(manifest, skipped);
|
|
20729
|
+
appendExclusionsToArtifact(fs12, summary.artifactPath, report);
|
|
20730
|
+
return { ...summary, exclusions: report };
|
|
20135
20731
|
}
|
|
20136
|
-
function deliverDestinationGitignore(fs12, destinationRoot) {
|
|
20732
|
+
function deliverDestinationGitignore(fs12, destinationRoot, manifest) {
|
|
20137
20733
|
const destinationPath = joinPosix7(
|
|
20138
20734
|
destinationRoot,
|
|
20139
20735
|
CLAUDE_GITIGNORE_RELATIVE_PATH
|
|
20140
20736
|
);
|
|
20737
|
+
const entry = manifest?.entries.find(
|
|
20738
|
+
(candidate) => matchesExclusionEntry(candidate, CLAUDE_GITIGNORE_RELATIVE_PATH)
|
|
20739
|
+
);
|
|
20740
|
+
if (entry !== void 0) {
|
|
20741
|
+
return {
|
|
20742
|
+
relativePath: CLAUDE_GITIGNORE_RELATIVE_PATH,
|
|
20743
|
+
entry: entry.normalized,
|
|
20744
|
+
line: entry.line,
|
|
20745
|
+
destinationStatus: fs12.isFile(destinationPath) ? "present" : "absent"
|
|
20746
|
+
};
|
|
20747
|
+
}
|
|
20141
20748
|
const currentText = fs12.isFile(destinationPath) ? fs12.readTextFile(destinationPath) : "";
|
|
20142
20749
|
const mergedText = mergeClaudeGitignore(currentText);
|
|
20143
20750
|
if (mergedText !== currentText) {
|
|
20144
20751
|
fs12.writeTextFile(destinationPath, mergedText);
|
|
20145
20752
|
}
|
|
20753
|
+
return void 0;
|
|
20146
20754
|
}
|
|
20147
20755
|
|
|
20148
20756
|
// ../../extensions/drm-copilot/src/lib/push-down/push-down-service-call.ts
|
|
@@ -20216,11 +20824,16 @@ function pushDownClaudeCustomizationsServiceCall(input) {
|
|
|
20216
20824
|
...input.memoryMode === void 0 ? {} : { memoryMode: input.memoryMode },
|
|
20217
20825
|
...input.clock === void 0 ? {} : { clock: input.clock }
|
|
20218
20826
|
});
|
|
20827
|
+
const lines = summary.exclusions === void 0 ? [] : renderExclusionLines(summary.exclusions);
|
|
20828
|
+
for (const line of lines) {
|
|
20829
|
+
input.log?.(line);
|
|
20830
|
+
}
|
|
20219
20831
|
return {
|
|
20220
20832
|
tool: "push_down_claude_customizations",
|
|
20221
20833
|
workspaceRoot: input.workspaceRoot,
|
|
20222
20834
|
summary: "Pushed bundled Claude Code customizations into the destination workspace.",
|
|
20223
|
-
artifacts: [normalizeGeneratedPath(summary.artifactPath)]
|
|
20835
|
+
artifacts: [normalizeGeneratedPath(summary.artifactPath)],
|
|
20836
|
+
...lines.length > 0 ? { warnings: lines } : {}
|
|
20224
20837
|
};
|
|
20225
20838
|
}
|
|
20226
20839
|
|
|
@@ -25127,6 +25740,7 @@ var MERGED_STATUSES = /* @__PURE__ */ new Set([
|
|
|
25127
25740
|
"merged",
|
|
25128
25741
|
"worktree_removed"
|
|
25129
25742
|
]);
|
|
25743
|
+
var NOT_STARTED_MERGE_STATUS = "not_started";
|
|
25130
25744
|
function isObject6(value) {
|
|
25131
25745
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25132
25746
|
}
|
|
@@ -25207,6 +25821,9 @@ function validateMergeStatusEnum(features) {
|
|
|
25207
25821
|
}
|
|
25208
25822
|
return errors;
|
|
25209
25823
|
}
|
|
25824
|
+
function hasStarted(feature) {
|
|
25825
|
+
return typeof feature["worktree_created_at"] === "string" || feature["merge_status"] !== NOT_STARTED_MERGE_STATUS;
|
|
25826
|
+
}
|
|
25210
25827
|
function validateWaveBarrierOrdering(features) {
|
|
25211
25828
|
const errors = [];
|
|
25212
25829
|
const byFolder = /* @__PURE__ */ new Map();
|
|
@@ -25223,6 +25840,9 @@ function validateWaveBarrierOrdering(features) {
|
|
|
25223
25840
|
if (typeof folder !== "string" || !Array.isArray(dependsOn)) {
|
|
25224
25841
|
continue;
|
|
25225
25842
|
}
|
|
25843
|
+
if (!hasStarted(feature)) {
|
|
25844
|
+
continue;
|
|
25845
|
+
}
|
|
25226
25846
|
const worktreeCreatedAt = feature["worktree_created_at"];
|
|
25227
25847
|
for (const dependency of dependsOn) {
|
|
25228
25848
|
const resolved = resolveFeatureReference(dependency, index);
|
|
@@ -25234,9 +25854,13 @@ function validateWaveBarrierOrdering(features) {
|
|
|
25234
25854
|
const depConfirmedAt = dependencyFeature["merge_confirmed_at"];
|
|
25235
25855
|
const statusViolation = typeof depMergeStatus !== "string" || !MERGED_STATUSES.has(depMergeStatus);
|
|
25236
25856
|
const timingViolation = typeof depConfirmedAt === "string" && typeof worktreeCreatedAt === "string" && depConfirmedAt > worktreeCreatedAt;
|
|
25237
|
-
if (statusViolation
|
|
25857
|
+
if (statusViolation) {
|
|
25238
25858
|
errors.push(
|
|
25239
|
-
`EPIC_WAVE_BARRIER_VIOLATION: ${folder} started
|
|
25859
|
+
`EPIC_WAVE_BARRIER_VIOLATION: ${folder} is treated as started while dependency ${String(dependency)} is not merged`
|
|
25860
|
+
);
|
|
25861
|
+
} else if (timingViolation) {
|
|
25862
|
+
errors.push(
|
|
25863
|
+
`EPIC_WAVE_BARRIER_VIOLATION: ${folder} worktree_created_at precedes dependency ${String(dependency)} merge_confirmed_at`
|
|
25240
25864
|
);
|
|
25241
25865
|
}
|
|
25242
25866
|
}
|
|
@@ -26582,6 +27206,201 @@ function validateEpicPlannerStateText(text2, options = {}) {
|
|
|
26582
27206
|
return errors;
|
|
26583
27207
|
}
|
|
26584
27208
|
|
|
27209
|
+
// ../../extensions/drm-copilot/src/lib/validate/orchestrator-state-blocked-reason.ts
|
|
27210
|
+
var MECHANICAL_BLOCKED_REASONS = /* @__PURE__ */ new Set([
|
|
27211
|
+
"spawn_agent_unavailable",
|
|
27212
|
+
"delegation_launch_failed",
|
|
27213
|
+
"delegate_no_receipt",
|
|
27214
|
+
"delegate_contract_incomplete",
|
|
27215
|
+
"validator_failed",
|
|
27216
|
+
"user_requested_stop"
|
|
27217
|
+
]);
|
|
27218
|
+
var NON_MECHANICAL_BLOCKED_REASONS = /* @__PURE__ */ new Set([
|
|
27219
|
+
"premise_falsified",
|
|
27220
|
+
"external_dependency",
|
|
27221
|
+
"policy_hold",
|
|
27222
|
+
"awaiting_ci",
|
|
27223
|
+
"human_decision_required"
|
|
27224
|
+
]);
|
|
27225
|
+
var VALID_BLOCKED_REASONS = /* @__PURE__ */ new Set([
|
|
27226
|
+
"none",
|
|
27227
|
+
...MECHANICAL_BLOCKED_REASONS,
|
|
27228
|
+
...NON_MECHANICAL_BLOCKED_REASONS
|
|
27229
|
+
]);
|
|
27230
|
+
|
|
27231
|
+
// ../../extensions/drm-copilot/src/lib/validate/orchestrator-state-promotion-tools.ts
|
|
27232
|
+
var FEATURE_PROMOTION_ENTRY_TOOL = "new_potential_entry";
|
|
27233
|
+
var BUG_PROMOTION_ENTRY_TOOL = "new_potential_bug_entry";
|
|
27234
|
+
var BUG_PROMOTION_TYPE = "bug";
|
|
27235
|
+
var PROMOTION_TYPE_KEY = "promotion-type";
|
|
27236
|
+
function resolvePromotionEntryTools(requiredMcpTools, state) {
|
|
27237
|
+
if (state[PROMOTION_TYPE_KEY] !== BUG_PROMOTION_TYPE) {
|
|
27238
|
+
return [...requiredMcpTools];
|
|
27239
|
+
}
|
|
27240
|
+
return requiredMcpTools.map(
|
|
27241
|
+
(tool) => tool === FEATURE_PROMOTION_ENTRY_TOOL ? BUG_PROMOTION_ENTRY_TOOL : tool
|
|
27242
|
+
);
|
|
27243
|
+
}
|
|
27244
|
+
|
|
27245
|
+
// ../../extensions/drm-copilot/src/lib/validate/orchestrator-state-issue-adoption.ts
|
|
27246
|
+
var ISSUE_ADOPTION_KEY = "issue_adoption";
|
|
27247
|
+
var POTENTIAL_TO_ISSUE_TOOL = "potential_to_issue";
|
|
27248
|
+
var ORIGIN_VALUES = /* @__PURE__ */ new Set([
|
|
27249
|
+
"transferred",
|
|
27250
|
+
"filed_before_orchestration",
|
|
27251
|
+
"epic_decomposition"
|
|
27252
|
+
]);
|
|
27253
|
+
var VERIFIED_VIA_VALUES = /* @__PURE__ */ new Set([
|
|
27254
|
+
"gh_issue_view",
|
|
27255
|
+
"gh_api_get",
|
|
27256
|
+
"github_mcp_issue_read"
|
|
27257
|
+
]);
|
|
27258
|
+
var WAIVABLE_TOOLS = /* @__PURE__ */ new Set([
|
|
27259
|
+
POTENTIAL_TO_ISSUE_TOOL,
|
|
27260
|
+
FEATURE_PROMOTION_ENTRY_TOOL,
|
|
27261
|
+
BUG_PROMOTION_ENTRY_TOOL
|
|
27262
|
+
]);
|
|
27263
|
+
var PROMOTION_ENTRY_TOOLS = /* @__PURE__ */ new Set([
|
|
27264
|
+
FEATURE_PROMOTION_ENTRY_TOOL,
|
|
27265
|
+
BUG_PROMOTION_ENTRY_TOOL
|
|
27266
|
+
]);
|
|
27267
|
+
var POTENTIAL_RECORD_PREFIX = "docs/features/potential/";
|
|
27268
|
+
var POTENTIAL_RECORD_SUFFIX = ".md";
|
|
27269
|
+
var ISSUE_NUM_PATTERN = /^[1-9][0-9]*$/;
|
|
27270
|
+
var ERROR_NOT_OBJECT = "Checkpoint issue_adoption must be an object when present.";
|
|
27271
|
+
var ERROR_ISSUE_NUM_FORMAT = "Checkpoint issue_adoption.issue_num must be a string of decimal digits without a leading zero.";
|
|
27272
|
+
var ERROR_ISSUE_NUM_MISMATCH = "Checkpoint issue_adoption.issue_num must equal the checkpoint issue-num.";
|
|
27273
|
+
var ERROR_ISSUE_URL = "Checkpoint issue_adoption.issue_url must end with /issues/ followed by issue_num.";
|
|
27274
|
+
var ERROR_ORIGIN = "Checkpoint issue_adoption.origin must be one of transferred, filed_before_orchestration, epic_decomposition.";
|
|
27275
|
+
var ERROR_VERIFIED_VIA = "Checkpoint issue_adoption.verified_via must be one of gh_issue_view, gh_api_get, github_mcp_issue_read.";
|
|
27276
|
+
var ERROR_VERIFIED_AT = "Checkpoint issue_adoption.verified_at must be present.";
|
|
27277
|
+
var ERROR_EVIDENCE = "Checkpoint issue_adoption.evidence must be a non-empty string.";
|
|
27278
|
+
var ERROR_WAIVED_TOOLS_SHAPE = "Checkpoint issue_adoption.waived_tools must be a non-empty list of tool names.";
|
|
27279
|
+
var ERROR_WAIVED_TOOLS_INCLUDE = "Checkpoint issue_adoption.waived_tools must include potential_to_issue.";
|
|
27280
|
+
function isPlainObject3(value) {
|
|
27281
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27282
|
+
}
|
|
27283
|
+
function isNonBlankString(value) {
|
|
27284
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
27285
|
+
}
|
|
27286
|
+
function validIssueNum(value) {
|
|
27287
|
+
return typeof value === "string" && ISSUE_NUM_PATTERN.test(value) ? value : null;
|
|
27288
|
+
}
|
|
27289
|
+
function issueIdentityErrors(adoption, state) {
|
|
27290
|
+
const errors = [];
|
|
27291
|
+
const issueNum = validIssueNum(adoption["issue_num"]);
|
|
27292
|
+
if (issueNum === null) {
|
|
27293
|
+
errors.push(ERROR_ISSUE_NUM_FORMAT);
|
|
27294
|
+
} else {
|
|
27295
|
+
const checkpointIssueNum = state["issue-num"];
|
|
27296
|
+
if (typeof checkpointIssueNum === "string" && checkpointIssueNum !== issueNum) {
|
|
27297
|
+
errors.push(ERROR_ISSUE_NUM_MISMATCH);
|
|
27298
|
+
}
|
|
27299
|
+
}
|
|
27300
|
+
const issueUrl = adoption["issue_url"];
|
|
27301
|
+
if (issueNum === null || typeof issueUrl !== "string" || !issueUrl.endsWith(`/issues/${issueNum}`)) {
|
|
27302
|
+
errors.push(ERROR_ISSUE_URL);
|
|
27303
|
+
}
|
|
27304
|
+
return errors;
|
|
27305
|
+
}
|
|
27306
|
+
function provenanceErrors(adoption) {
|
|
27307
|
+
const errors = [];
|
|
27308
|
+
const origin = adoption["origin"];
|
|
27309
|
+
if (typeof origin !== "string" || !ORIGIN_VALUES.has(origin)) {
|
|
27310
|
+
errors.push(ERROR_ORIGIN);
|
|
27311
|
+
}
|
|
27312
|
+
const verifiedVia = adoption["verified_via"];
|
|
27313
|
+
if (typeof verifiedVia !== "string" || !VERIFIED_VIA_VALUES.has(verifiedVia)) {
|
|
27314
|
+
errors.push(ERROR_VERIFIED_VIA);
|
|
27315
|
+
}
|
|
27316
|
+
const verifiedAt = adoption["verified_at"];
|
|
27317
|
+
if (verifiedAt === void 0 || verifiedAt === null || typeof verifiedAt === "string" && verifiedAt.trim().length === 0) {
|
|
27318
|
+
errors.push(ERROR_VERIFIED_AT);
|
|
27319
|
+
}
|
|
27320
|
+
if (!isNonBlankString(adoption["evidence"])) {
|
|
27321
|
+
errors.push(ERROR_EVIDENCE);
|
|
27322
|
+
}
|
|
27323
|
+
return errors;
|
|
27324
|
+
}
|
|
27325
|
+
function waivedToolList(value) {
|
|
27326
|
+
if (!Array.isArray(value)) {
|
|
27327
|
+
return null;
|
|
27328
|
+
}
|
|
27329
|
+
const items = value;
|
|
27330
|
+
if (items.length === 0 || !items.every((item) => isNonBlankString(item))) {
|
|
27331
|
+
return null;
|
|
27332
|
+
}
|
|
27333
|
+
return items;
|
|
27334
|
+
}
|
|
27335
|
+
function waivedToolErrors(waived, options) {
|
|
27336
|
+
const errors = [];
|
|
27337
|
+
const seen = /* @__PURE__ */ new Set();
|
|
27338
|
+
for (const tool of waived) {
|
|
27339
|
+
if (seen.has(tool)) {
|
|
27340
|
+
errors.push(
|
|
27341
|
+
`Checkpoint issue_adoption.waived_tools lists a tool more than once: ${tool}.`
|
|
27342
|
+
);
|
|
27343
|
+
} else if (!WAIVABLE_TOOLS.has(tool)) {
|
|
27344
|
+
errors.push(
|
|
27345
|
+
`Checkpoint issue_adoption.waived_tools names a tool that cannot be waived: ${tool}.`
|
|
27346
|
+
);
|
|
27347
|
+
} else if (!options.requiredMcpTools.includes(tool)) {
|
|
27348
|
+
errors.push(
|
|
27349
|
+
`Checkpoint issue_adoption.waived_tools names a tool that is not required by route ${options.routeId}: ${tool}.`
|
|
27350
|
+
);
|
|
27351
|
+
} else if (options.successfulTools.has(tool)) {
|
|
27352
|
+
errors.push(
|
|
27353
|
+
`Checkpoint issue_adoption.waived_tools names a tool that has a successful MCP receipt: ${tool}.`
|
|
27354
|
+
);
|
|
27355
|
+
}
|
|
27356
|
+
seen.add(tool);
|
|
27357
|
+
}
|
|
27358
|
+
if (!seen.has(POTENTIAL_TO_ISSUE_TOOL)) {
|
|
27359
|
+
errors.push(ERROR_WAIVED_TOOLS_INCLUDE);
|
|
27360
|
+
}
|
|
27361
|
+
return errors;
|
|
27362
|
+
}
|
|
27363
|
+
function potentialRecordErrors(waived, potentialRecord) {
|
|
27364
|
+
if (typeof potentialRecord === "string" && potentialRecord.startsWith(POTENTIAL_RECORD_PREFIX) && potentialRecord.endsWith(POTENTIAL_RECORD_SUFFIX)) {
|
|
27365
|
+
return [];
|
|
27366
|
+
}
|
|
27367
|
+
const errors = [];
|
|
27368
|
+
const reported = /* @__PURE__ */ new Set();
|
|
27369
|
+
for (const tool of waived) {
|
|
27370
|
+
if (PROMOTION_ENTRY_TOOLS.has(tool) && !reported.has(tool)) {
|
|
27371
|
+
errors.push(
|
|
27372
|
+
`Checkpoint issue_adoption.potential_record must name a markdown file under docs/features/potential/ when waiving ${tool}.`
|
|
27373
|
+
);
|
|
27374
|
+
reported.add(tool);
|
|
27375
|
+
}
|
|
27376
|
+
}
|
|
27377
|
+
return errors;
|
|
27378
|
+
}
|
|
27379
|
+
function resolveIssueAdoption(state, options) {
|
|
27380
|
+
if (!Object.prototype.hasOwnProperty.call(state, ISSUE_ADOPTION_KEY)) {
|
|
27381
|
+
return { errors: [], waivedTools: /* @__PURE__ */ new Set() };
|
|
27382
|
+
}
|
|
27383
|
+
const adoption = state[ISSUE_ADOPTION_KEY];
|
|
27384
|
+
if (!isPlainObject3(adoption)) {
|
|
27385
|
+
return { errors: [ERROR_NOT_OBJECT], waivedTools: /* @__PURE__ */ new Set() };
|
|
27386
|
+
}
|
|
27387
|
+
const errors = [
|
|
27388
|
+
...issueIdentityErrors(adoption, state),
|
|
27389
|
+
...provenanceErrors(adoption)
|
|
27390
|
+
];
|
|
27391
|
+
const waived = waivedToolList(adoption["waived_tools"]);
|
|
27392
|
+
if (waived === null) {
|
|
27393
|
+
errors.push(ERROR_WAIVED_TOOLS_SHAPE);
|
|
27394
|
+
return { errors, waivedTools: /* @__PURE__ */ new Set() };
|
|
27395
|
+
}
|
|
27396
|
+
errors.push(...waivedToolErrors(waived, options));
|
|
27397
|
+
errors.push(...potentialRecordErrors(waived, adoption["potential_record"]));
|
|
27398
|
+
if (errors.length > 0) {
|
|
27399
|
+
return { errors, waivedTools: /* @__PURE__ */ new Set() };
|
|
27400
|
+
}
|
|
27401
|
+
return { errors: [], waivedTools: new Set(waived) };
|
|
27402
|
+
}
|
|
27403
|
+
|
|
26585
27404
|
// ../../extensions/drm-copilot/src/lib/validate/orchestrator-state-routing.ts
|
|
26586
27405
|
var ROUTING_MATRIX_RELATIVE_PATH = "config/orchestration-routing.json";
|
|
26587
27406
|
var MANDATORY_ROUTE_PHASES = {
|
|
@@ -26770,7 +27589,10 @@ function validateRoutingContract(state, options = {}) {
|
|
|
26770
27589
|
const errors = [];
|
|
26771
27590
|
const requiredAgents = routeList(rawRoute, "required_agents");
|
|
26772
27591
|
const requiredSkills = routeList(rawRoute, "required_skills");
|
|
26773
|
-
const requiredMcpTools =
|
|
27592
|
+
const requiredMcpTools = resolvePromotionEntryTools(
|
|
27593
|
+
routeList(rawRoute, "required_mcp_tools"),
|
|
27594
|
+
state
|
|
27595
|
+
);
|
|
26774
27596
|
if (stateList(state, "required_agents", requiredAgents) === null) {
|
|
26775
27597
|
errors.push(
|
|
26776
27598
|
`Checkpoint required_agents must match routing matrix for route ${routeId}.`
|
|
@@ -26799,11 +27621,20 @@ function validateRoutingContract(state, options = {}) {
|
|
|
26799
27621
|
}
|
|
26800
27622
|
}
|
|
26801
27623
|
const actualTools = mcpTools(state);
|
|
27624
|
+
const adoption = resolveIssueAdoption(state, {
|
|
27625
|
+
routeId,
|
|
27626
|
+
requiredMcpTools,
|
|
27627
|
+
successfulTools: actualTools
|
|
27628
|
+
});
|
|
26802
27629
|
for (const tool of requiredMcpTools) {
|
|
27630
|
+
if (adoption.waivedTools.has(tool)) {
|
|
27631
|
+
continue;
|
|
27632
|
+
}
|
|
26803
27633
|
if (!actualTools.has(tool)) {
|
|
26804
27634
|
errors.push(`Checkpoint missing successful MCP receipt: ${tool}.`);
|
|
26805
27635
|
}
|
|
26806
27636
|
}
|
|
27637
|
+
errors.push(...adoption.errors);
|
|
26807
27638
|
errors.push(...validateEmptyListField(state, "local_execution_overrides"));
|
|
26808
27639
|
errors.push(...validateEmptyListField(state, "delegation_bypasses"));
|
|
26809
27640
|
errors.push(...validateLifecycleOperations(state));
|
|
@@ -26949,14 +27780,137 @@ function validateHumanInteraction(humanInteraction) {
|
|
|
26949
27780
|
return errors;
|
|
26950
27781
|
}
|
|
26951
27782
|
|
|
27783
|
+
// ../../extensions/drm-copilot/src/lib/validate/orchestrator-state-remediation-accounting.ts
|
|
27784
|
+
var REVIEW_OUTCOMES_KEY = "review_outcomes";
|
|
27785
|
+
var REVIEW_VERDICTS = [
|
|
27786
|
+
"PASS",
|
|
27787
|
+
"REMEDIATION_REQUIRED",
|
|
27788
|
+
"HALT_NON_REMEDIABLE",
|
|
27789
|
+
"AWAITING_CI"
|
|
27790
|
+
];
|
|
27791
|
+
var REMEDIABILITY_CLASSES = [
|
|
27792
|
+
"autonomous",
|
|
27793
|
+
"external_dependency",
|
|
27794
|
+
"policy_hold",
|
|
27795
|
+
"awaiting_ci",
|
|
27796
|
+
"human_decision_required"
|
|
27797
|
+
];
|
|
27798
|
+
var HALT_CLASSES = /* @__PURE__ */ new Set([
|
|
27799
|
+
"external_dependency",
|
|
27800
|
+
"policy_hold",
|
|
27801
|
+
"human_decision_required"
|
|
27802
|
+
]);
|
|
27803
|
+
var REMEDIABLE_CLASS = "autonomous";
|
|
27804
|
+
function isObject11(value) {
|
|
27805
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27806
|
+
}
|
|
27807
|
+
function pythonRepr8(value) {
|
|
27808
|
+
if (value === null || value === void 0) {
|
|
27809
|
+
return "None";
|
|
27810
|
+
}
|
|
27811
|
+
if (value === true) {
|
|
27812
|
+
return "True";
|
|
27813
|
+
}
|
|
27814
|
+
if (value === false) {
|
|
27815
|
+
return "False";
|
|
27816
|
+
}
|
|
27817
|
+
return String(value);
|
|
27818
|
+
}
|
|
27819
|
+
function deriveReviewVerdict(remediabilities) {
|
|
27820
|
+
for (const value of remediabilities) {
|
|
27821
|
+
if (!REMEDIABILITY_CLASSES.includes(value)) {
|
|
27822
|
+
throw new RangeError(`invalid remediability: ${value}`);
|
|
27823
|
+
}
|
|
27824
|
+
}
|
|
27825
|
+
if (remediabilities.length === 0) {
|
|
27826
|
+
return "PASS";
|
|
27827
|
+
}
|
|
27828
|
+
if (remediabilities.includes(REMEDIABLE_CLASS)) {
|
|
27829
|
+
return "REMEDIATION_REQUIRED";
|
|
27830
|
+
}
|
|
27831
|
+
if (remediabilities.some((value) => HALT_CLASSES.has(value))) {
|
|
27832
|
+
return "HALT_NON_REMEDIABLE";
|
|
27833
|
+
}
|
|
27834
|
+
return "AWAITING_CI";
|
|
27835
|
+
}
|
|
27836
|
+
function validateReviewOutcome(index, outcome) {
|
|
27837
|
+
const errors = [];
|
|
27838
|
+
const prefix = `Checkpoint remediation review outcome #${index}`;
|
|
27839
|
+
const verdict = outcome["verdict"];
|
|
27840
|
+
if (typeof verdict !== "string" || !REVIEW_VERDICTS.includes(verdict)) {
|
|
27841
|
+
errors.push(
|
|
27842
|
+
`${prefix} verdict must be one of PASS, REMEDIATION_REQUIRED, HALT_NON_REMEDIABLE, AWAITING_CI; got: ${pythonRepr8(verdict)}`
|
|
27843
|
+
);
|
|
27844
|
+
}
|
|
27845
|
+
const classes = [];
|
|
27846
|
+
const findings = outcome["findings"];
|
|
27847
|
+
if (!Array.isArray(findings)) {
|
|
27848
|
+
errors.push(`${prefix} findings must be a list.`);
|
|
27849
|
+
} else {
|
|
27850
|
+
findings.forEach((finding, findingIndex) => {
|
|
27851
|
+
if (!isObject11(finding)) {
|
|
27852
|
+
errors.push(`${prefix} finding #${findingIndex} must be an object.`);
|
|
27853
|
+
return;
|
|
27854
|
+
}
|
|
27855
|
+
const remediability = finding["remediability"];
|
|
27856
|
+
if (typeof remediability !== "string" || !REMEDIABILITY_CLASSES.includes(remediability)) {
|
|
27857
|
+
errors.push(
|
|
27858
|
+
`${prefix} finding #${findingIndex} remediability must be one of autonomous, external_dependency, policy_hold, awaiting_ci, human_decision_required; got: ${pythonRepr8(remediability)}`
|
|
27859
|
+
);
|
|
27860
|
+
return;
|
|
27861
|
+
}
|
|
27862
|
+
classes.push(remediability);
|
|
27863
|
+
});
|
|
27864
|
+
}
|
|
27865
|
+
if (errors.length === 0) {
|
|
27866
|
+
const expected = deriveReviewVerdict(classes);
|
|
27867
|
+
if (verdict !== expected) {
|
|
27868
|
+
errors.push(
|
|
27869
|
+
`${prefix} verdict ${pythonRepr8(verdict)} does not match its findings (expected ${expected}).`
|
|
27870
|
+
);
|
|
27871
|
+
}
|
|
27872
|
+
}
|
|
27873
|
+
return errors;
|
|
27874
|
+
}
|
|
27875
|
+
function validateReviewOutcomes(loop) {
|
|
27876
|
+
if (!Object.prototype.hasOwnProperty.call(loop, REVIEW_OUTCOMES_KEY)) {
|
|
27877
|
+
return [];
|
|
27878
|
+
}
|
|
27879
|
+
const outcomes = loop[REVIEW_OUTCOMES_KEY];
|
|
27880
|
+
if (!Array.isArray(outcomes)) {
|
|
27881
|
+
return ["Checkpoint remediation_loop review_outcomes must be a list."];
|
|
27882
|
+
}
|
|
27883
|
+
const errors = [];
|
|
27884
|
+
outcomes.forEach((outcome, index) => {
|
|
27885
|
+
if (!isObject11(outcome)) {
|
|
27886
|
+
errors.push(
|
|
27887
|
+
`Checkpoint remediation review outcome #${index} must be an object.`
|
|
27888
|
+
);
|
|
27889
|
+
return;
|
|
27890
|
+
}
|
|
27891
|
+
errors.push(...validateReviewOutcome(index, outcome));
|
|
27892
|
+
});
|
|
27893
|
+
return errors;
|
|
27894
|
+
}
|
|
27895
|
+
|
|
26952
27896
|
// ../../extensions/drm-copilot/src/lib/validate/orchestrator-state-remediation.ts
|
|
26953
27897
|
var REMEDIATION_LOOP_KEY = "remediation_loop";
|
|
26954
27898
|
var REMEDIATION_CYCLES_KEY = "cycles";
|
|
26955
27899
|
var EXECUTION_STATUSES_REQUIRING_CLEAR_PREFLIGHT = /* @__PURE__ */ new Set(["in_progress", "complete", "failed"]);
|
|
26956
27900
|
var PREFLIGHT_CLEARED_STATUS = "clear";
|
|
26957
|
-
|
|
27901
|
+
var COMPLETED_ATTEMPTS_KEY = "completed_attempts";
|
|
27902
|
+
var CANDIDATE_APPLIED_KEY = "candidate_applied";
|
|
27903
|
+
var OPENED_BY_REVIEW_KEY = "opened_by_review";
|
|
27904
|
+
var COMPLETED_EXECUTION_STATUS = "complete";
|
|
27905
|
+
function isObject12(value) {
|
|
26958
27906
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26959
27907
|
}
|
|
27908
|
+
function isStrictInteger(value) {
|
|
27909
|
+
return typeof value === "number" && Number.isInteger(value);
|
|
27910
|
+
}
|
|
27911
|
+
function hasKey(value, key) {
|
|
27912
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
27913
|
+
}
|
|
26960
27914
|
function validateRemediationCycle(index, cycle) {
|
|
26961
27915
|
const errors = [];
|
|
26962
27916
|
const planPath = cycle["plan_path"];
|
|
@@ -26968,7 +27922,7 @@ function validateRemediationCycle(index, cycle) {
|
|
|
26968
27922
|
const executionStatus = cycle["execution_status"];
|
|
26969
27923
|
if (typeof executionStatus === "string" && EXECUTION_STATUSES_REQUIRING_CLEAR_PREFLIGHT.has(executionStatus)) {
|
|
26970
27924
|
const preflight = cycle["preflight"];
|
|
26971
|
-
const preflightStatus =
|
|
27925
|
+
const preflightStatus = isObject12(preflight) ? preflight["final_status"] : void 0;
|
|
26972
27926
|
if (preflightStatus !== PREFLIGHT_CLEARED_STATUS) {
|
|
26973
27927
|
errors.push(
|
|
26974
27928
|
`Checkpoint remediation cycle #${index} execution_status is ${executionStatus} but preflight.final_status is not 'clear'.`
|
|
@@ -26982,22 +27936,79 @@ function validateRemediationCycle(index, cycle) {
|
|
|
26982
27936
|
}
|
|
26983
27937
|
return errors;
|
|
26984
27938
|
}
|
|
27939
|
+
function opensRemediationReview(openedByReview, outcomes) {
|
|
27940
|
+
if (!isStrictInteger(openedByReview) || !Array.isArray(outcomes)) {
|
|
27941
|
+
return false;
|
|
27942
|
+
}
|
|
27943
|
+
if (openedByReview < 0 || openedByReview >= outcomes.length) {
|
|
27944
|
+
return false;
|
|
27945
|
+
}
|
|
27946
|
+
const target = outcomes[openedByReview];
|
|
27947
|
+
return isObject12(target) && target["verdict"] === "REMEDIATION_REQUIRED";
|
|
27948
|
+
}
|
|
27949
|
+
function validateRemediationAccounting(loop, cycleList) {
|
|
27950
|
+
const errors = [];
|
|
27951
|
+
const outcomes = loop[REVIEW_OUTCOMES_KEY];
|
|
27952
|
+
let appliedCount = 0;
|
|
27953
|
+
(cycleList ?? []).forEach((cycle, index) => {
|
|
27954
|
+
if (!isObject12(cycle)) {
|
|
27955
|
+
return;
|
|
27956
|
+
}
|
|
27957
|
+
const prefix = `Checkpoint remediation cycle #${index}`;
|
|
27958
|
+
if (hasKey(cycle, CANDIDATE_APPLIED_KEY)) {
|
|
27959
|
+
const candidateApplied = cycle[CANDIDATE_APPLIED_KEY];
|
|
27960
|
+
if (typeof candidateApplied !== "boolean") {
|
|
27961
|
+
errors.push(`${prefix} candidate_applied must be a boolean.`);
|
|
27962
|
+
} else if (candidateApplied) {
|
|
27963
|
+
appliedCount += 1;
|
|
27964
|
+
if (cycle["execution_status"] !== COMPLETED_EXECUTION_STATUS) {
|
|
27965
|
+
errors.push(
|
|
27966
|
+
`${prefix} candidate_applied is true but execution_status is not 'complete'.`
|
|
27967
|
+
);
|
|
27968
|
+
}
|
|
27969
|
+
}
|
|
27970
|
+
}
|
|
27971
|
+
if (hasKey(cycle, OPENED_BY_REVIEW_KEY) && !opensRemediationReview(cycle[OPENED_BY_REVIEW_KEY], outcomes)) {
|
|
27972
|
+
errors.push(
|
|
27973
|
+
`${prefix} opened_by_review must reference a review outcome whose verdict is REMEDIATION_REQUIRED.`
|
|
27974
|
+
);
|
|
27975
|
+
}
|
|
27976
|
+
});
|
|
27977
|
+
if (hasKey(loop, COMPLETED_ATTEMPTS_KEY)) {
|
|
27978
|
+
const completedAttempts = loop[COMPLETED_ATTEMPTS_KEY];
|
|
27979
|
+
if (!isStrictInteger(completedAttempts) || completedAttempts < 0) {
|
|
27980
|
+
errors.push(
|
|
27981
|
+
"Checkpoint remediation_loop completed_attempts must be a non-negative integer."
|
|
27982
|
+
);
|
|
27983
|
+
} else if (completedAttempts !== appliedCount) {
|
|
27984
|
+
errors.push(
|
|
27985
|
+
`Checkpoint remediation_loop completed_attempts is ${completedAttempts} but ${appliedCount} cycles have candidate_applied true.`
|
|
27986
|
+
);
|
|
27987
|
+
}
|
|
27988
|
+
}
|
|
27989
|
+
return errors;
|
|
27990
|
+
}
|
|
26985
27991
|
function validateRemediationLoop(remediationLoop) {
|
|
26986
27992
|
const errors = [];
|
|
26987
|
-
if (!
|
|
27993
|
+
if (!isObject12(remediationLoop)) {
|
|
26988
27994
|
return errors;
|
|
26989
27995
|
}
|
|
26990
27996
|
const cycles = remediationLoop[REMEDIATION_CYCLES_KEY];
|
|
26991
|
-
|
|
26992
|
-
|
|
27997
|
+
let cycleList = null;
|
|
27998
|
+
if (Array.isArray(cycles)) {
|
|
27999
|
+
cycleList = cycles;
|
|
28000
|
+
cycles.forEach((cycle, index) => {
|
|
28001
|
+
if (!isObject12(cycle)) {
|
|
28002
|
+
errors.push(
|
|
28003
|
+
`Checkpoint remediation cycle #${index} must be an object.`
|
|
28004
|
+
);
|
|
28005
|
+
return;
|
|
28006
|
+
}
|
|
28007
|
+
errors.push(...validateRemediationCycle(index, cycle));
|
|
28008
|
+
});
|
|
26993
28009
|
}
|
|
26994
|
-
|
|
26995
|
-
|
|
26996
|
-
errors.push(`Checkpoint remediation cycle #${index} must be an object.`);
|
|
26997
|
-
return;
|
|
26998
|
-
}
|
|
26999
|
-
errors.push(...validateRemediationCycle(index, cycle));
|
|
27000
|
-
});
|
|
28010
|
+
errors.push(...validateReviewOutcomes(remediationLoop));
|
|
28011
|
+
errors.push(...validateRemediationAccounting(remediationLoop, cycleList));
|
|
27001
28012
|
return errors;
|
|
27002
28013
|
}
|
|
27003
28014
|
|
|
@@ -27011,7 +28022,7 @@ var OUT_OF_SCOPE_STEP_KEYS = [
|
|
|
27011
28022
|
"step9_status",
|
|
27012
28023
|
"step10_status"
|
|
27013
28024
|
];
|
|
27014
|
-
function
|
|
28025
|
+
function pythonRepr9(value) {
|
|
27015
28026
|
if (value === void 0 || value === null) {
|
|
27016
28027
|
return "None";
|
|
27017
28028
|
}
|
|
@@ -27026,11 +28037,11 @@ function pythonRepr8(value) {
|
|
|
27026
28037
|
return String(value);
|
|
27027
28038
|
}
|
|
27028
28039
|
if (Array.isArray(value)) {
|
|
27029
|
-
return `[${value.map(
|
|
28040
|
+
return `[${value.map(pythonRepr9).join(", ")}]`;
|
|
27030
28041
|
}
|
|
27031
28042
|
if (typeof value === "object") {
|
|
27032
28043
|
const entries = Object.entries(value).map(
|
|
27033
|
-
([key, item]) => `${
|
|
28044
|
+
([key, item]) => `${pythonRepr9(key)}: ${pythonRepr9(item)}`
|
|
27034
28045
|
);
|
|
27035
28046
|
return `{${entries.join(", ")}}`;
|
|
27036
28047
|
}
|
|
@@ -27044,13 +28055,13 @@ function validatePreparationTerminalContract(state) {
|
|
|
27044
28055
|
const errors = [];
|
|
27045
28056
|
if (state["next_step"] !== EXPECTED_NEXT_STEP) {
|
|
27046
28057
|
errors.push(
|
|
27047
|
-
`Preparation checkpoint next_step must be ${
|
|
28058
|
+
`Preparation checkpoint next_step must be ${pythonRepr9(EXPECTED_NEXT_STEP)}, found ${pythonRepr9(state["next_step"])}.`
|
|
27048
28059
|
);
|
|
27049
28060
|
}
|
|
27050
28061
|
for (const key of OUT_OF_SCOPE_STEP_KEYS) {
|
|
27051
28062
|
if (state[key] !== "not-applicable") {
|
|
27052
28063
|
errors.push(
|
|
27053
|
-
`Preparation checkpoint ${key} must be 'not-applicable', found ${
|
|
28064
|
+
`Preparation checkpoint ${key} must be 'not-applicable', found ${pythonRepr9(state[key])}.`
|
|
27054
28065
|
);
|
|
27055
28066
|
}
|
|
27056
28067
|
}
|
|
@@ -27066,18 +28077,18 @@ var DELEGATING_AGENTS = /* @__PURE__ */ new Set([
|
|
|
27066
28077
|
"prd-feature",
|
|
27067
28078
|
"pr-author"
|
|
27068
28079
|
]);
|
|
27069
|
-
function
|
|
28080
|
+
function isObject13(value) {
|
|
27070
28081
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27071
28082
|
}
|
|
27072
28083
|
function delegatedAgents(state) {
|
|
27073
28084
|
const agents = /* @__PURE__ */ new Set();
|
|
27074
28085
|
let receipts = state["delegation_receipts"];
|
|
27075
|
-
if (
|
|
28086
|
+
if (isObject13(receipts)) {
|
|
27076
28087
|
receipts = receipts["agents"];
|
|
27077
28088
|
}
|
|
27078
28089
|
if (Array.isArray(receipts)) {
|
|
27079
28090
|
for (const receipt of receipts) {
|
|
27080
|
-
if (!
|
|
28091
|
+
if (!isObject13(receipt)) {
|
|
27081
28092
|
continue;
|
|
27082
28093
|
}
|
|
27083
28094
|
const agentName = receipt["agent_name"];
|
|
@@ -27101,7 +28112,7 @@ function validateModelRoutingExistence(state) {
|
|
|
27101
28112
|
const receipts = state["model_routing_receipts"];
|
|
27102
28113
|
if (Array.isArray(receipts)) {
|
|
27103
28114
|
for (const receipt of receipts) {
|
|
27104
|
-
if (!
|
|
28115
|
+
if (!isObject13(receipt)) {
|
|
27105
28116
|
continue;
|
|
27106
28117
|
}
|
|
27107
28118
|
const agent = receipt["agent"];
|
|
@@ -27150,15 +28161,6 @@ var VALID_STEP_STATUS = /* @__PURE__ */ new Set([
|
|
|
27150
28161
|
"in_progress",
|
|
27151
28162
|
"completed"
|
|
27152
28163
|
]);
|
|
27153
|
-
var VALID_BLOCKED_REASONS = /* @__PURE__ */ new Set([
|
|
27154
|
-
"none",
|
|
27155
|
-
"spawn_agent_unavailable",
|
|
27156
|
-
"delegation_launch_failed",
|
|
27157
|
-
"delegate_no_receipt",
|
|
27158
|
-
"delegate_contract_incomplete",
|
|
27159
|
-
"validator_failed",
|
|
27160
|
-
"user_requested_stop"
|
|
27161
|
-
]);
|
|
27162
28164
|
var REQUIRED_RECEIPT_KEYS = [
|
|
27163
28165
|
"step",
|
|
27164
28166
|
"agent_name",
|
|
@@ -27198,13 +28200,13 @@ function isValidStepStatus(key, value) {
|
|
|
27198
28200
|
}
|
|
27199
28201
|
return STEP_SPECIFIC_EXTRA_STATUS.get(key)?.has(value) === true;
|
|
27200
28202
|
}
|
|
27201
|
-
function
|
|
28203
|
+
function isObject14(value) {
|
|
27202
28204
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27203
28205
|
}
|
|
27204
28206
|
function validateListDelegationReceipts(receipts) {
|
|
27205
28207
|
const errors = [];
|
|
27206
28208
|
receipts.forEach((receipt, index) => {
|
|
27207
|
-
if (!
|
|
28209
|
+
if (!isObject14(receipt)) {
|
|
27208
28210
|
errors.push(`Checkpoint delegation receipt #${index} must be an object.`);
|
|
27209
28211
|
return;
|
|
27210
28212
|
}
|
|
@@ -27246,7 +28248,7 @@ function validateNamespacedDelegationReceipts(receipts) {
|
|
|
27246
28248
|
if (promotionReceipts === void 0 || promotionReceipts === null) {
|
|
27247
28249
|
return errors;
|
|
27248
28250
|
}
|
|
27249
|
-
if (!
|
|
28251
|
+
if (!isObject14(promotionReceipts)) {
|
|
27250
28252
|
errors.push(
|
|
27251
28253
|
"Checkpoint delegation_receipts.promotion must be an object namespace."
|
|
27252
28254
|
);
|
|
@@ -27281,7 +28283,7 @@ function validateOrchestratorStateText(text2, options = {}) {
|
|
|
27281
28283
|
`Checkpoint is not valid JSON: ${exc instanceof Error ? exc.message : String(exc)}`
|
|
27282
28284
|
];
|
|
27283
28285
|
}
|
|
27284
|
-
if (!
|
|
28286
|
+
if (!isObject14(state)) {
|
|
27285
28287
|
return ["Checkpoint root must be a JSON object."];
|
|
27286
28288
|
}
|
|
27287
28289
|
const stateMap = state;
|
|
@@ -27306,7 +28308,7 @@ function validateOrchestratorStateText(text2, options = {}) {
|
|
|
27306
28308
|
if (receipts !== void 0 && receipts !== null) {
|
|
27307
28309
|
if (Array.isArray(receipts)) {
|
|
27308
28310
|
errors.push(...validateListDelegationReceipts(receipts));
|
|
27309
|
-
} else if (
|
|
28311
|
+
} else if (isObject14(receipts)) {
|
|
27310
28312
|
errors.push(...validateNamespacedDelegationReceipts(receipts));
|
|
27311
28313
|
} else {
|
|
27312
28314
|
errors.push(
|
|
@@ -28343,10 +29345,10 @@ var PROHIBITED_ANY_LEVEL_KEYS = words(
|
|
|
28343
29345
|
"depends_on integration_branch epic_merge_pr"
|
|
28344
29346
|
);
|
|
28345
29347
|
var ROOT_PATH = "<root>";
|
|
28346
|
-
function
|
|
29348
|
+
function isObject15(value) {
|
|
28347
29349
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28348
29350
|
}
|
|
28349
|
-
function
|
|
29351
|
+
function pythonRepr10(value) {
|
|
28350
29352
|
if (value === null || value === void 0) {
|
|
28351
29353
|
return "None";
|
|
28352
29354
|
}
|
|
@@ -28357,18 +29359,18 @@ function pythonRepr9(value) {
|
|
|
28357
29359
|
return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
28358
29360
|
}
|
|
28359
29361
|
if (Array.isArray(value)) {
|
|
28360
|
-
return `[${value.map(
|
|
29362
|
+
return `[${value.map(pythonRepr10).join(", ")}]`;
|
|
28361
29363
|
}
|
|
28362
|
-
if (
|
|
29364
|
+
if (isObject15(value)) {
|
|
28363
29365
|
const pairs = Object.entries(value).map(
|
|
28364
|
-
([key, item]) => `${
|
|
29366
|
+
([key, item]) => `${pythonRepr10(key)}: ${pythonRepr10(item)}`
|
|
28365
29367
|
);
|
|
28366
29368
|
return `{${pairs.join(", ")}}`;
|
|
28367
29369
|
}
|
|
28368
29370
|
return String(value);
|
|
28369
29371
|
}
|
|
28370
29372
|
function pythonStr2(value) {
|
|
28371
|
-
return typeof value === "string" ? value :
|
|
29373
|
+
return typeof value === "string" ? value : pythonRepr10(value);
|
|
28372
29374
|
}
|
|
28373
29375
|
function isEnumMember(members, value) {
|
|
28374
29376
|
return typeof value === "string" && members.includes(value);
|
|
@@ -28385,25 +29387,25 @@ function isPositiveInteger(value) {
|
|
|
28385
29387
|
function isNonNegativeInteger(value) {
|
|
28386
29388
|
return isIntegral(value) && value >= 0;
|
|
28387
29389
|
}
|
|
28388
|
-
function
|
|
29390
|
+
function isStringList2(value) {
|
|
28389
29391
|
return Array.isArray(value) && value.every(isNonEmptyString2);
|
|
28390
29392
|
}
|
|
28391
29393
|
function inBoundedRange(value, minimum, maximum) {
|
|
28392
29394
|
return isIntegral(value) && value >= minimum && value <= maximum;
|
|
28393
29395
|
}
|
|
28394
29396
|
function enumError(context, field, members, value) {
|
|
28395
|
-
return `${context} ${field} must be one of ${members.join(", ")}; found: ${
|
|
29397
|
+
return `${context} ${field} must be one of ${members.join(", ")}; found: ${pythonRepr10(value)}.`;
|
|
28396
29398
|
}
|
|
28397
29399
|
function itemContext(context, index) {
|
|
28398
29400
|
return `${context} items[${index}]`;
|
|
28399
29401
|
}
|
|
28400
29402
|
function validateBlastRadiusBlock(radius, context) {
|
|
28401
|
-
if (!
|
|
29403
|
+
if (!isObject15(radius)) {
|
|
28402
29404
|
return [`${context} blast_radius must be an object.`];
|
|
28403
29405
|
}
|
|
28404
29406
|
const errors = [];
|
|
28405
29407
|
for (const field of BLAST_RADIUS_LIST_FIELDS) {
|
|
28406
|
-
if (!
|
|
29408
|
+
if (!isStringList2(radius[field])) {
|
|
28407
29409
|
errors.push(
|
|
28408
29410
|
`${context} blast_radius.${field} must be a list of non-empty strings.`
|
|
28409
29411
|
);
|
|
@@ -28434,25 +29436,25 @@ function validateMergeStatus(record3, context, state) {
|
|
|
28434
29436
|
}
|
|
28435
29437
|
if (isEnumMember(MERGED_MERGE_STATUSES, mergeStatus) && state !== "merged") {
|
|
28436
29438
|
return [
|
|
28437
|
-
`${context} merge_status ${
|
|
29439
|
+
`${context} merge_status ${pythonRepr10(mergeStatus)} requires state 'merged'; found: ${pythonRepr10(state)}.`
|
|
28438
29440
|
];
|
|
28439
29441
|
}
|
|
28440
29442
|
if (isEnumMember(BLOCKED_MERGE_STATUSES, mergeStatus) && state !== "blocked") {
|
|
28441
29443
|
return [
|
|
28442
|
-
`${context} merge_status ${
|
|
29444
|
+
`${context} merge_status ${pythonRepr10(mergeStatus)} requires state 'blocked'; found: ${pythonRepr10(state)}.`
|
|
28443
29445
|
];
|
|
28444
29446
|
}
|
|
28445
29447
|
return [];
|
|
28446
29448
|
}
|
|
28447
29449
|
function validateItemRecord(item, context, requireKind = false) {
|
|
28448
|
-
if (!
|
|
29450
|
+
if (!isObject15(item)) {
|
|
28449
29451
|
return [`${context} must be an object.`];
|
|
28450
29452
|
}
|
|
28451
29453
|
const errors = [];
|
|
28452
29454
|
const issueNum = item["issue_num"];
|
|
28453
29455
|
if (!isPositiveInteger(issueNum)) {
|
|
28454
29456
|
errors.push(
|
|
28455
|
-
`${context} issue_num must be a positive integer; found: ${
|
|
29457
|
+
`${context} issue_num must be a positive integer; found: ${pythonRepr10(issueNum)}.`
|
|
28456
29458
|
);
|
|
28457
29459
|
}
|
|
28458
29460
|
if (!isNonEmptyString2(item["feature_folder"])) {
|
|
@@ -28483,7 +29485,7 @@ function validateItems(items, context, requireKind = false) {
|
|
|
28483
29485
|
errors.push(
|
|
28484
29486
|
...validateItemRecord(entry, itemContext(context, index), requireKind)
|
|
28485
29487
|
);
|
|
28486
|
-
if (!
|
|
29488
|
+
if (!isObject15(entry)) {
|
|
28487
29489
|
return;
|
|
28488
29490
|
}
|
|
28489
29491
|
const issueNum = entry["issue_num"];
|
|
@@ -28502,7 +29504,7 @@ function validateItems(items, context, requireKind = false) {
|
|
|
28502
29504
|
}
|
|
28503
29505
|
function prohibitedKeyErrors(value, path16, context, keys) {
|
|
28504
29506
|
const errors = [];
|
|
28505
|
-
if (
|
|
29507
|
+
if (isObject15(value)) {
|
|
28506
29508
|
for (const [key, child] of Object.entries(value)) {
|
|
28507
29509
|
if (keys.includes(key)) {
|
|
28508
29510
|
errors.push(`${context} carries prohibited key '${key}' at ${path16}.`);
|
|
@@ -28521,7 +29523,7 @@ function prohibitedKeyErrors(value, path16, context, keys) {
|
|
|
28521
29523
|
}
|
|
28522
29524
|
function scanProhibitedKeys(root, context, deepKeys = PROHIBITED_ANY_LEVEL_KEYS, topLevelKeys = []) {
|
|
28523
29525
|
const errors = prohibitedKeyErrors(root, ROOT_PATH, context, deepKeys);
|
|
28524
|
-
if (
|
|
29526
|
+
if (isObject15(root) && topLevelKeys.length > 0) {
|
|
28525
29527
|
for (const key of topLevelKeys) {
|
|
28526
29528
|
if (key in root) {
|
|
28527
29529
|
errors.push(
|
|
@@ -28537,7 +29539,7 @@ function scanProhibitedKeys(root, context, deepKeys = PROHIBITED_ANY_LEVEL_KEYS,
|
|
|
28537
29539
|
var VIOLATION_PREFIX = "PARALLEL_COHORT_BARRIER_VIOLATION";
|
|
28538
29540
|
var ITEM_START_TIMESTAMP_FIELD = "worktree_created_at";
|
|
28539
29541
|
var MERGE_CONFIRMATION_TIMESTAMP_FIELD = "merged_at";
|
|
28540
|
-
var
|
|
29542
|
+
var NOT_STARTED_MERGE_STATUS2 = "not_started";
|
|
28541
29543
|
var GATING_KEYS = ["conflict_edges", "cohorts"];
|
|
28542
29544
|
var FOLDER_HINT_PREFIXES = [
|
|
28543
29545
|
"docs/features/active/",
|
|
@@ -28560,7 +29562,7 @@ function buildReferenceIndex(items) {
|
|
|
28560
29562
|
return { records, byFolderHint };
|
|
28561
29563
|
}
|
|
28562
29564
|
for (const entry of items) {
|
|
28563
|
-
if (!
|
|
29565
|
+
if (!isObject15(entry)) {
|
|
28564
29566
|
continue;
|
|
28565
29567
|
}
|
|
28566
29568
|
const issueNum = entry["issue_num"];
|
|
@@ -28595,7 +29597,7 @@ function cohortIndexByItem(cohorts, recolorGeneration, references) {
|
|
|
28595
29597
|
return assignments;
|
|
28596
29598
|
}
|
|
28597
29599
|
for (const entry of cohorts) {
|
|
28598
|
-
if (!
|
|
29600
|
+
if (!isObject15(entry) || entry["generation"] !== recolorGeneration) {
|
|
28599
29601
|
continue;
|
|
28600
29602
|
}
|
|
28601
29603
|
const cohortIndex = entry["index"];
|
|
@@ -28612,13 +29614,13 @@ function cohortIndexByItem(cohorts, recolorGeneration, references) {
|
|
|
28612
29614
|
}
|
|
28613
29615
|
return assignments;
|
|
28614
29616
|
}
|
|
28615
|
-
function
|
|
29617
|
+
function hasStarted2(record3) {
|
|
28616
29618
|
const start = record3[ITEM_START_TIMESTAMP_FIELD];
|
|
28617
29619
|
if (typeof start === "string" && start.trim().length > 0) {
|
|
28618
29620
|
return true;
|
|
28619
29621
|
}
|
|
28620
29622
|
const mergeStatus = record3["merge_status"];
|
|
28621
|
-
return typeof mergeStatus === "string" && mergeStatus !==
|
|
29623
|
+
return typeof mergeStatus === "string" && mergeStatus !== NOT_STARTED_MERGE_STATUS2;
|
|
28622
29624
|
}
|
|
28623
29625
|
function satisfiesBarrier(record3) {
|
|
28624
29626
|
return isEnumMember(MERGED_MERGE_STATUSES, record3["merge_status"]);
|
|
@@ -28646,7 +29648,7 @@ function violationEndpoints(first, second, assignments, records) {
|
|
|
28646
29648
|
if (earlier === void 0 || later === void 0) {
|
|
28647
29649
|
return null;
|
|
28648
29650
|
}
|
|
28649
|
-
const statusViolation =
|
|
29651
|
+
const statusViolation = hasStarted2(later) && !satisfiesBarrier(earlier);
|
|
28650
29652
|
if (statusViolation || mergeConfirmedAfterStart(earlier, later)) {
|
|
28651
29653
|
return [earlierKey, laterKey];
|
|
28652
29654
|
}
|
|
@@ -28668,7 +29670,7 @@ function validateCohortBarrierOrdering(state) {
|
|
|
28668
29670
|
);
|
|
28669
29671
|
const errors = [];
|
|
28670
29672
|
for (const entry of edges) {
|
|
28671
|
-
if (!
|
|
29673
|
+
if (!isObject15(entry)) {
|
|
28672
29674
|
continue;
|
|
28673
29675
|
}
|
|
28674
29676
|
const first = resolveReference(entry["a"], references);
|
|
@@ -28706,14 +29708,14 @@ function validateMutationItemKey(entry, entryContext, op, issueNums) {
|
|
|
28706
29708
|
if (op === "close") {
|
|
28707
29709
|
if (!isNone(itemKey)) {
|
|
28708
29710
|
return [
|
|
28709
|
-
`${entryContext} item_key must be null for op 'close'; found: ${
|
|
29711
|
+
`${entryContext} item_key must be null for op 'close'; found: ${pythonRepr10(itemKey)}.`
|
|
28710
29712
|
];
|
|
28711
29713
|
}
|
|
28712
29714
|
return [];
|
|
28713
29715
|
}
|
|
28714
29716
|
if (isEnumMember(OPS_REQUIRING_ITEM_KEY, op) && !resolves(itemKey, issueNums)) {
|
|
28715
29717
|
return [
|
|
28716
|
-
`${entryContext} item_key ${
|
|
29718
|
+
`${entryContext} item_key ${pythonRepr10(itemKey)} does not resolve to an items[].issue_num.`
|
|
28717
29719
|
];
|
|
28718
29720
|
}
|
|
28719
29721
|
return [];
|
|
@@ -28725,12 +29727,12 @@ function validateMutationStateField(entry, entryContext, field, op, nullOps) {
|
|
|
28725
29727
|
}
|
|
28726
29728
|
if (isEnumMember(nullOps, op)) {
|
|
28727
29729
|
return [
|
|
28728
|
-
`${entryContext} ${field} must be null for op ${
|
|
29730
|
+
`${entryContext} ${field} must be null for op ${pythonRepr10(op)}; found: ${pythonRepr10(value)}.`
|
|
28729
29731
|
];
|
|
28730
29732
|
}
|
|
28731
29733
|
if (!isEnumMember(VALID_ITEM_STATES, value)) {
|
|
28732
29734
|
return [
|
|
28733
|
-
`${entryContext} ${field} must be null or one of ${VALID_ITEM_STATES.join(", ")}; found: ${
|
|
29735
|
+
`${entryContext} ${field} must be null or one of ${VALID_ITEM_STATES.join(", ")}; found: ${pythonRepr10(value)}.`
|
|
28734
29736
|
];
|
|
28735
29737
|
}
|
|
28736
29738
|
return [];
|
|
@@ -28740,14 +29742,14 @@ function validateMutationDisposition(entry, entryContext, op) {
|
|
|
28740
29742
|
if (op === "remove" && entry["prior_state"] === "in_flight") {
|
|
28741
29743
|
if (!isEnumMember(VALID_DISPOSITIONS, disposition)) {
|
|
28742
29744
|
return [
|
|
28743
|
-
`${entryContext} disposition must be one of ${VALID_DISPOSITIONS.join(", ")} for an in-flight removal; found: ${
|
|
29745
|
+
`${entryContext} disposition must be one of ${VALID_DISPOSITIONS.join(", ")} for an in-flight removal; found: ${pythonRepr10(disposition)}.`
|
|
28744
29746
|
];
|
|
28745
29747
|
}
|
|
28746
29748
|
return [];
|
|
28747
29749
|
}
|
|
28748
29750
|
if (!isNone(disposition)) {
|
|
28749
29751
|
return [
|
|
28750
|
-
`${entryContext} disposition must be null unless op is 'remove' with prior_state 'in_flight'; found: ${
|
|
29752
|
+
`${entryContext} disposition must be null unless op is 'remove' with prior_state 'in_flight'; found: ${pythonRepr10(disposition)}.`
|
|
28751
29753
|
];
|
|
28752
29754
|
}
|
|
28753
29755
|
return [];
|
|
@@ -28756,7 +29758,7 @@ function validateMutationGeneration(entry, entryContext, recolorGeneration) {
|
|
|
28756
29758
|
const generation = entry["recolor_generation"];
|
|
28757
29759
|
if (!isNonNegativeInteger(generation)) {
|
|
28758
29760
|
return [
|
|
28759
|
-
`${entryContext} recolor_generation must be a non-negative integer; found: ${
|
|
29761
|
+
`${entryContext} recolor_generation must be a non-negative integer; found: ${pythonRepr10(generation)}.`
|
|
28760
29762
|
];
|
|
28761
29763
|
}
|
|
28762
29764
|
if (isNonNegativeInteger(recolorGeneration) && typeof generation === "number" && typeof recolorGeneration === "number" && generation > recolorGeneration) {
|
|
@@ -28773,7 +29775,7 @@ function validateMutations(mutations, issueNums, recolorGeneration, context) {
|
|
|
28773
29775
|
const errors = [];
|
|
28774
29776
|
mutations.forEach((entry, position) => {
|
|
28775
29777
|
const entryContext = `${context} mutations[${position}]`;
|
|
28776
|
-
if (!
|
|
29778
|
+
if (!isObject15(entry)) {
|
|
28777
29779
|
errors.push(`${entryContext} must be an object.`);
|
|
28778
29780
|
return;
|
|
28779
29781
|
}
|
|
@@ -28817,25 +29819,25 @@ function validateDriftEvents(events, issueNums, context) {
|
|
|
28817
29819
|
const errors = [];
|
|
28818
29820
|
events.forEach((entry, position) => {
|
|
28819
29821
|
const entryContext = `${context} drift_events[${position}]`;
|
|
28820
|
-
if (!
|
|
29822
|
+
if (!isObject15(entry)) {
|
|
28821
29823
|
errors.push(`${entryContext} must be an object.`);
|
|
28822
29824
|
return;
|
|
28823
29825
|
}
|
|
28824
29826
|
const itemKey = entry["item_key"];
|
|
28825
29827
|
if (!resolves(itemKey, issueNums)) {
|
|
28826
29828
|
errors.push(
|
|
28827
|
-
`${entryContext} item_key ${
|
|
29829
|
+
`${entryContext} item_key ${pythonRepr10(itemKey)} does not resolve to an items[].issue_num.`
|
|
28828
29830
|
);
|
|
28829
29831
|
}
|
|
28830
29832
|
for (const field of ["declared", "observed"]) {
|
|
28831
|
-
if (!
|
|
29833
|
+
if (!isStringList2(entry[field])) {
|
|
28832
29834
|
errors.push(
|
|
28833
29835
|
`${entryContext} ${field} must be a list of non-empty strings.`
|
|
28834
29836
|
);
|
|
28835
29837
|
}
|
|
28836
29838
|
}
|
|
28837
29839
|
const escapedPaths = entry["escaped_paths"];
|
|
28838
|
-
if (!
|
|
29840
|
+
if (!isStringList2(escapedPaths) || !Array.isArray(escapedPaths) || escapedPaths.length === 0) {
|
|
28839
29841
|
errors.push(
|
|
28840
29842
|
`${entryContext} escaped_paths must be a non-empty list of non-empty strings.`
|
|
28841
29843
|
);
|
|
@@ -28862,7 +29864,7 @@ function collectItemKeysAndStates(items) {
|
|
|
28862
29864
|
return pairs;
|
|
28863
29865
|
}
|
|
28864
29866
|
for (const entry of items) {
|
|
28865
|
-
if (!
|
|
29867
|
+
if (!isObject15(entry)) {
|
|
28866
29868
|
continue;
|
|
28867
29869
|
}
|
|
28868
29870
|
const issueNum = entry["issue_num"];
|
|
@@ -28880,13 +29882,13 @@ function validateCohortEntry(entry, entryContext, issueNums, recolorGeneration)
|
|
|
28880
29882
|
const index = entry["index"];
|
|
28881
29883
|
if (!isNonNegativeInteger(index)) {
|
|
28882
29884
|
errors.push(
|
|
28883
|
-
`${entryContext} index must be a non-negative integer; found: ${
|
|
29885
|
+
`${entryContext} index must be a non-negative integer; found: ${pythonRepr10(index)}.`
|
|
28884
29886
|
);
|
|
28885
29887
|
}
|
|
28886
29888
|
const generation = entry["generation"];
|
|
28887
29889
|
if (!isNonNegativeInteger(generation)) {
|
|
28888
29890
|
errors.push(
|
|
28889
|
-
`${entryContext} generation must be a non-negative integer; found: ${
|
|
29891
|
+
`${entryContext} generation must be a non-negative integer; found: ${pythonRepr10(generation)}.`
|
|
28890
29892
|
);
|
|
28891
29893
|
} else if (recolorGeneration !== null && typeof generation === "number" && generation > recolorGeneration) {
|
|
28892
29894
|
errors.push(
|
|
@@ -28901,7 +29903,7 @@ function validateCohortEntry(entry, entryContext, issueNums, recolorGeneration)
|
|
|
28901
29903
|
for (const key of itemKeys) {
|
|
28902
29904
|
if (typeof key !== "number" || !Number.isInteger(key) || !issueNums.has(key)) {
|
|
28903
29905
|
errors.push(
|
|
28904
|
-
`${entryContext} item_keys entry ${
|
|
29906
|
+
`${entryContext} item_keys entry ${pythonRepr10(key)} does not resolve to an items[].issue_num.`
|
|
28905
29907
|
);
|
|
28906
29908
|
}
|
|
28907
29909
|
}
|
|
@@ -28912,7 +29914,7 @@ function validateCohortShapes(cohorts, issueNums, recolorGeneration, context) {
|
|
|
28912
29914
|
const generationOk = isNonNegativeInteger(recolorGeneration);
|
|
28913
29915
|
if (!generationOk) {
|
|
28914
29916
|
errors.push(
|
|
28915
|
-
`${context} recolor_generation must be a non-negative integer; found: ${
|
|
29917
|
+
`${context} recolor_generation must be a non-negative integer; found: ${pythonRepr10(recolorGeneration)}.`
|
|
28916
29918
|
);
|
|
28917
29919
|
}
|
|
28918
29920
|
if (!Array.isArray(cohorts)) {
|
|
@@ -28922,7 +29924,7 @@ function validateCohortShapes(cohorts, issueNums, recolorGeneration, context) {
|
|
|
28922
29924
|
const bound = generationOk && typeof recolorGeneration === "number" ? recolorGeneration : null;
|
|
28923
29925
|
cohorts.forEach((entry, position) => {
|
|
28924
29926
|
const entryContext = `${context} cohorts[${position}]`;
|
|
28925
|
-
if (!
|
|
29927
|
+
if (!isObject15(entry)) {
|
|
28926
29928
|
errors.push(`${entryContext} must be an object.`);
|
|
28927
29929
|
return;
|
|
28928
29930
|
}
|
|
@@ -28934,7 +29936,7 @@ function currentGenerationCohorts(cohorts, recolorGeneration) {
|
|
|
28934
29936
|
if (!isNonNegativeInteger(recolorGeneration) || !Array.isArray(cohorts)) {
|
|
28935
29937
|
return [];
|
|
28936
29938
|
}
|
|
28937
|
-
return cohorts.filter(
|
|
29939
|
+
return cohorts.filter(isObject15).filter((entry) => entry["generation"] === recolorGeneration);
|
|
28938
29940
|
}
|
|
28939
29941
|
function validateCurrentGenerationCohorts(cohorts, items, recolorGeneration, context) {
|
|
28940
29942
|
const current = currentGenerationCohorts(cohorts, recolorGeneration);
|
|
@@ -28979,7 +29981,7 @@ function validateCurrentGenerationCohorts(cohorts, items, recolorGeneration, con
|
|
|
28979
29981
|
continue;
|
|
28980
29982
|
}
|
|
28981
29983
|
errors.push(
|
|
28982
|
-
`${context} item ${issueNum} in state ${
|
|
29984
|
+
`${context} item ${issueNum} in state ${pythonRepr10(state)} must appear in exactly one current-generation cohort; found ${count}.`
|
|
28983
29985
|
);
|
|
28984
29986
|
}
|
|
28985
29987
|
return errors;
|
|
@@ -28987,7 +29989,7 @@ function validateCurrentGenerationCohorts(cohorts, items, recolorGeneration, con
|
|
|
28987
29989
|
function validateCurrentCohortBound(currentCohort, cohorts, recolorGeneration, context) {
|
|
28988
29990
|
if (!isNonNegativeInteger(currentCohort) || typeof currentCohort !== "number") {
|
|
28989
29991
|
return [
|
|
28990
|
-
`${context} current_cohort must be a non-negative integer; found: ${
|
|
29992
|
+
`${context} current_cohort must be a non-negative integer; found: ${pythonRepr10(currentCohort)}.`
|
|
28991
29993
|
];
|
|
28992
29994
|
}
|
|
28993
29995
|
const indices = [];
|
|
@@ -29017,7 +30019,7 @@ function validateEdgeEndpoints(entry, entryContext, issueNums) {
|
|
|
29017
30019
|
endpoints.set(field, value);
|
|
29018
30020
|
} else {
|
|
29019
30021
|
errors.push(
|
|
29020
|
-
`${entryContext} ${field} ${
|
|
30022
|
+
`${entryContext} ${field} ${pythonRepr10(value)} does not resolve to an items[].issue_num.`
|
|
29021
30023
|
);
|
|
29022
30024
|
}
|
|
29023
30025
|
}
|
|
@@ -29047,7 +30049,7 @@ function validateConflictEdges(edges, issueNums, context) {
|
|
|
29047
30049
|
const duplicates = /* @__PURE__ */ new Map();
|
|
29048
30050
|
edges.forEach((entry, position) => {
|
|
29049
30051
|
const entryContext = `${context} conflict_edges[${position}]`;
|
|
29050
|
-
if (!
|
|
30052
|
+
if (!isObject15(entry)) {
|
|
29051
30053
|
errors.push(`${entryContext} must be an object.`);
|
|
29052
30054
|
return;
|
|
29053
30055
|
}
|
|
@@ -29126,7 +30128,7 @@ function validateIdentity(state) {
|
|
|
29126
30128
|
const routeId = state["route_id"];
|
|
29127
30129
|
if ("route_id" in state && routeId !== EXPECTED_ROUTE_ID2) {
|
|
29128
30130
|
errors.push(
|
|
29129
|
-
`${CONTEXT} route_id must be '${EXPECTED_ROUTE_ID2}'; found: ${
|
|
30131
|
+
`${CONTEXT} route_id must be '${EXPECTED_ROUTE_ID2}'; found: ${pythonRepr10(routeId)}.`
|
|
29130
30132
|
);
|
|
29131
30133
|
}
|
|
29132
30134
|
const mode = state["mode"];
|
|
@@ -29136,7 +30138,7 @@ function validateIdentity(state) {
|
|
|
29136
30138
|
const concurrency = state["max_concurrency"];
|
|
29137
30139
|
if ("max_concurrency" in state && !inBoundedRange(concurrency, MIN_CONCURRENCY, MAX_CONCURRENCY)) {
|
|
29138
30140
|
errors.push(
|
|
29139
|
-
`${CONTEXT} max_concurrency must be an integer from ${MIN_CONCURRENCY} through ${MAX_CONCURRENCY}; found: ${
|
|
30141
|
+
`${CONTEXT} max_concurrency must be an integer from ${MIN_CONCURRENCY} through ${MAX_CONCURRENCY}; found: ${pythonRepr10(concurrency)}.`
|
|
29140
30142
|
);
|
|
29141
30143
|
}
|
|
29142
30144
|
return errors;
|
|
@@ -29192,7 +30194,7 @@ function recordsCloseMutation(state) {
|
|
|
29192
30194
|
return false;
|
|
29193
30195
|
}
|
|
29194
30196
|
return mutations.some(
|
|
29195
|
-
(entry) =>
|
|
30197
|
+
(entry) => isObject15(entry) && entry["op"] === "close"
|
|
29196
30198
|
);
|
|
29197
30199
|
}
|
|
29198
30200
|
function validateCompletion2(state) {
|
|
@@ -29200,7 +30202,7 @@ function validateCompletion2(state) {
|
|
|
29200
30202
|
const items = state["items"];
|
|
29201
30203
|
const entries = Array.isArray(items) ? items : [];
|
|
29202
30204
|
entries.forEach((entry, index) => {
|
|
29203
|
-
if (!
|
|
30205
|
+
if (!isObject15(entry)) {
|
|
29204
30206
|
return;
|
|
29205
30207
|
}
|
|
29206
30208
|
if (entry["state"] === "withdrawn") {
|
|
@@ -29209,7 +30211,7 @@ function validateCompletion2(state) {
|
|
|
29209
30211
|
const mergeStatus = entry["merge_status"];
|
|
29210
30212
|
if (!isEnumMember(MERGED_MERGE_STATUSES, mergeStatus)) {
|
|
29211
30213
|
errors.push(
|
|
29212
|
-
`${itemContext(CONTEXT, index)} completion validation failed: merge_status is not merged or worktree_removed; found: ${
|
|
30214
|
+
`${itemContext(CONTEXT, index)} completion validation failed: merge_status is not merged or worktree_removed; found: ${pythonRepr10(mergeStatus)}.`
|
|
29213
30215
|
);
|
|
29214
30216
|
}
|
|
29215
30217
|
});
|
|
@@ -29228,7 +30230,7 @@ function validateParallelOrchestratorStateText(text2, options = {}) {
|
|
|
29228
30230
|
const detail = error2 instanceof Error ? error2.message : String(error2);
|
|
29229
30231
|
return [`${CONTEXT} is not valid JSON: ${detail}.`];
|
|
29230
30232
|
}
|
|
29231
|
-
if (!
|
|
30233
|
+
if (!isObject15(state)) {
|
|
29232
30234
|
return [`${CONTEXT} root must be a JSON object.`];
|
|
29233
30235
|
}
|
|
29234
30236
|
const errors = [];
|
|
@@ -29306,7 +30308,7 @@ function validateIdentity2(state) {
|
|
|
29306
30308
|
const concurrency = state["max_concurrency"];
|
|
29307
30309
|
if ("max_concurrency" in state && !inBoundedRange(concurrency, MIN_CONCURRENCY2, MAX_CONCURRENCY2)) {
|
|
29308
30310
|
errors.push(
|
|
29309
|
-
`${CONTEXT2} max_concurrency must be an integer from ${MIN_CONCURRENCY2} through ${MAX_CONCURRENCY2}; found: ${
|
|
30311
|
+
`${CONTEXT2} max_concurrency must be an integer from ${MIN_CONCURRENCY2} through ${MAX_CONCURRENCY2}; found: ${pythonRepr10(concurrency)}.`
|
|
29310
30312
|
);
|
|
29311
30313
|
}
|
|
29312
30314
|
return errors;
|
|
@@ -29317,7 +30319,7 @@ function itemRecords(items) {
|
|
|
29317
30319
|
}
|
|
29318
30320
|
const records = [];
|
|
29319
30321
|
items.forEach((entry, index) => {
|
|
29320
|
-
if (
|
|
30322
|
+
if (isObject15(entry)) {
|
|
29321
30323
|
records.push({ index, record: entry });
|
|
29322
30324
|
}
|
|
29323
30325
|
});
|
|
@@ -29386,13 +30388,13 @@ function validateReadyItem(record3, entryContext) {
|
|
|
29386
30388
|
const preparationStatus = record3["preparation_status"];
|
|
29387
30389
|
if (preparationStatus !== READY_PREPARATION_STATUS) {
|
|
29388
30390
|
errors.push(
|
|
29389
|
-
`${entryContext} preparation_status must be ${
|
|
30391
|
+
`${entryContext} preparation_status must be ${pythonRepr10(READY_PREPARATION_STATUS)}; found: ${pythonRepr10(preparationStatus)}.`
|
|
29390
30392
|
);
|
|
29391
30393
|
}
|
|
29392
30394
|
const preflightStatus = record3["preflight_status"];
|
|
29393
30395
|
if (preflightStatus !== READY_PREFLIGHT_STATUS) {
|
|
29394
30396
|
errors.push(
|
|
29395
|
-
`${entryContext} preflight_status must be ${
|
|
30397
|
+
`${entryContext} preflight_status must be ${pythonRepr10(READY_PREFLIGHT_STATUS)}; found: ${pythonRepr10(preflightStatus)}.`
|
|
29396
30398
|
);
|
|
29397
30399
|
}
|
|
29398
30400
|
for (const key of READY_ITEM_PATH_KEYS) {
|
|
@@ -29401,10 +30403,10 @@ function validateReadyItem(record3, entryContext) {
|
|
|
29401
30403
|
}
|
|
29402
30404
|
}
|
|
29403
30405
|
const radius = record3["blast_radius"];
|
|
29404
|
-
const source =
|
|
30406
|
+
const source = isObject15(radius) ? radius["source"] : null;
|
|
29405
30407
|
if (source !== READY_RADIUS_SOURCE) {
|
|
29406
30408
|
errors.push(
|
|
29407
|
-
`${entryContext} blast_radius.source must be ${
|
|
30409
|
+
`${entryContext} blast_radius.source must be ${pythonRepr10(READY_RADIUS_SOURCE)} for execution readiness; found: ${pythonRepr10(source)}.`
|
|
29408
30410
|
);
|
|
29409
30411
|
}
|
|
29410
30412
|
return errors;
|
|
@@ -29426,14 +30428,14 @@ function validateReadyGate(state) {
|
|
|
29426
30428
|
const nextStep = state["next_step"];
|
|
29427
30429
|
if (nextStep !== READY_NEXT_STEP2) {
|
|
29428
30430
|
errors.push(
|
|
29429
|
-
`${CONTEXT2} next_step must be ${
|
|
30431
|
+
`${CONTEXT2} next_step must be ${pythonRepr10(READY_NEXT_STEP2)}; found: ${pythonRepr10(nextStep)}.`
|
|
29430
30432
|
);
|
|
29431
30433
|
}
|
|
29432
30434
|
const expectedKickoff = kickoffPathFor(state["parallel_slug"]);
|
|
29433
30435
|
const kickoffPromptPath = state["kickoff_prompt_path"];
|
|
29434
30436
|
if (kickoffPromptPath !== expectedKickoff) {
|
|
29435
30437
|
errors.push(
|
|
29436
|
-
`${CONTEXT2} kickoff_prompt_path must be ${
|
|
30438
|
+
`${CONTEXT2} kickoff_prompt_path must be ${pythonRepr10(expectedKickoff)}; found: ${pythonRepr10(kickoffPromptPath)}.`
|
|
29437
30439
|
);
|
|
29438
30440
|
}
|
|
29439
30441
|
return errors;
|
|
@@ -29446,7 +30448,7 @@ function validateParallelPlannerStateText(text2, options = {}) {
|
|
|
29446
30448
|
const detail = error2 instanceof Error ? error2.message : String(error2);
|
|
29447
30449
|
return [`${CONTEXT2} is not valid JSON: ${detail}.`];
|
|
29448
30450
|
}
|
|
29449
|
-
if (!
|
|
30451
|
+
if (!isObject15(state)) {
|
|
29450
30452
|
return [`${CONTEXT2} root must be a JSON object.`];
|
|
29451
30453
|
}
|
|
29452
30454
|
const errors = [];
|
|
@@ -33418,7 +34420,7 @@ function resolveReadinessSignal(fs12, featureDir) {
|
|
|
33418
34420
|
}
|
|
33419
34421
|
return [null, null];
|
|
33420
34422
|
}
|
|
33421
|
-
function
|
|
34423
|
+
function relativeToPosix8(root, path16) {
|
|
33422
34424
|
const normalizedRoot = toPosixPath2(root).replace(/\/+$/u, "");
|
|
33423
34425
|
const normalized = toPosixPath2(path16);
|
|
33424
34426
|
if (normalized.startsWith(`${normalizedRoot}/`)) {
|
|
@@ -33451,7 +34453,7 @@ function discoverCanonicalEvidenceFiles(fs12, root, feature) {
|
|
|
33451
34453
|
for (const pattern of CANONICAL_GLOBS) {
|
|
33452
34454
|
for (const candidate of fs12.glob(featureRoot, pattern)) {
|
|
33453
34455
|
if (fs12.isFile(candidate)) {
|
|
33454
|
-
discovered.add(
|
|
34456
|
+
discovered.add(relativeToPosix9(normalizedRoot, candidate));
|
|
33455
34457
|
}
|
|
33456
34458
|
}
|
|
33457
34459
|
}
|
|
@@ -33544,7 +34546,7 @@ function parseIntegerStrict(value) {
|
|
|
33544
34546
|
}
|
|
33545
34547
|
return Number.parseInt(value, 10);
|
|
33546
34548
|
}
|
|
33547
|
-
function
|
|
34549
|
+
function relativeToPosix9(root, absolute) {
|
|
33548
34550
|
const normalized = toPosixPath2(absolute);
|
|
33549
34551
|
if (normalized.startsWith(`${root}/`)) {
|
|
33550
34552
|
return normalized.slice(root.length + 1);
|
|
@@ -33732,11 +34734,11 @@ function buildContextFiles(params) {
|
|
|
33732
34734
|
const contextFiles = [];
|
|
33733
34735
|
for (const path16 of candidatePaths) {
|
|
33734
34736
|
if (fs12.exists(path16)) {
|
|
33735
|
-
contextFiles.push(
|
|
34737
|
+
contextFiles.push(relativeToPosix8(root, path16));
|
|
33736
34738
|
}
|
|
33737
34739
|
}
|
|
33738
34740
|
if (readinessSource !== null) {
|
|
33739
|
-
contextFiles.push(
|
|
34741
|
+
contextFiles.push(relativeToPosix8(root, readinessSource));
|
|
33740
34742
|
}
|
|
33741
34743
|
const evidenceContextFiles = discoverCanonicalEvidenceFiles(
|
|
33742
34744
|
fs12,
|
|
@@ -35261,6 +36263,10 @@ function promotePotential(options) {
|
|
|
35261
36263
|
filesystem.ensureDir(promotedDir);
|
|
35262
36264
|
const destPath = posixJoin(promotedDir, posixBasename(resolved));
|
|
35263
36265
|
filesystem.move(resolved, destPath);
|
|
36266
|
+
if (!filesystem.exists(destPath)) {
|
|
36267
|
+
emitLine(`Promoted file missing after move: ${destPath}`);
|
|
36268
|
+
return { exitCode: 1, messages };
|
|
36269
|
+
}
|
|
35264
36270
|
emitLine(`Moved potential file to promoted folder: ${destPath}`);
|
|
35265
36271
|
return { exitCode: 0, messages, destination: destPath };
|
|
35266
36272
|
}
|