@ifrankwang/openspec-agents 0.127.0 → 0.130.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.mcp-server/cli.mjs +518 -138
- package/README.md +1 -1
- package/assets/agents/openspec-developer.md +2 -51
- package/assets/agents/openspec-reviewer.md +28 -20
- package/assets/workflows/task-simple.yaml +13 -12
- package/assets/workflows/task.yaml +4 -4
- package/dsh/cordis.patch.yml +29 -71
- package/package.json +1 -1
- package/src/adapters/deepseek-harness/index.ts +1 -1
- package/src/core/constants.ts +7 -0
- package/src/core/git.ts +61 -0
- package/src/core/tools/gate.ts +5 -0
- package/src/core/tools/lifecycle.ts +9 -8
- package/src/core/tools/schemas.ts +5 -1
- package/src/core/tools/submit.ts +64 -11
- package/src/core/views.ts +21 -0
- package/src/core/workflow/status.ts +41 -13
package/.mcp-server/cli.mjs
CHANGED
|
@@ -3053,7 +3053,25 @@ var require_utils = __commonJS(function(exports, module) {
|
|
|
3053
3053
|
var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
|
|
3054
3054
|
var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
3055
3055
|
var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
3056
|
-
var isPathCharacter = RegExp.prototype.test.bind(/^[
|
|
3056
|
+
var isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u);
|
|
3057
|
+
var isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u);
|
|
3058
|
+
var isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u);
|
|
3059
|
+
var BYTE_HEX = new Array(256);
|
|
3060
|
+
{
|
|
3061
|
+
const HEX_DIGITS = "0123456789ABCDEF";
|
|
3062
|
+
for (let i = 0;i < 256; i++) {
|
|
3063
|
+
BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
function percentEncodeNonAscii(cp) {
|
|
3067
|
+
if (cp < 2048) {
|
|
3068
|
+
return BYTE_HEX[192 | cp >> 6] + BYTE_HEX[128 | cp & 63];
|
|
3069
|
+
}
|
|
3070
|
+
if (cp < 65536) {
|
|
3071
|
+
return BYTE_HEX[224 | cp >> 12] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3072
|
+
}
|
|
3073
|
+
return BYTE_HEX[240 | cp >> 18] + BYTE_HEX[128 | cp >> 12 & 63] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3074
|
+
}
|
|
3057
3075
|
function stringArrayToHexStripped(input) {
|
|
3058
3076
|
let acc = "";
|
|
3059
3077
|
let code = 0;
|
|
@@ -3078,91 +3096,122 @@ var require_utils = __commonJS(function(exports, module) {
|
|
|
3078
3096
|
}
|
|
3079
3097
|
return acc;
|
|
3080
3098
|
}
|
|
3099
|
+
var isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/);
|
|
3100
|
+
var isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/);
|
|
3101
|
+
var isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/);
|
|
3081
3102
|
var nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u);
|
|
3082
|
-
function
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
} else {
|
|
3092
|
-
output.error = true;
|
|
3093
|
-
return false;
|
|
3103
|
+
function isZoneIdentifier(zone) {
|
|
3104
|
+
if (zone.length === 0)
|
|
3105
|
+
return false;
|
|
3106
|
+
for (let i = 0;i < zone.length; i++) {
|
|
3107
|
+
if (isZoneCharacter(zone[i]))
|
|
3108
|
+
continue;
|
|
3109
|
+
if (zone[i] === "%" && i + 2 < zone.length && isHexPair(zone.slice(i + 1, i + 3))) {
|
|
3110
|
+
i += 2;
|
|
3111
|
+
continue;
|
|
3094
3112
|
}
|
|
3095
|
-
|
|
3113
|
+
return false;
|
|
3096
3114
|
}
|
|
3097
3115
|
return true;
|
|
3098
3116
|
}
|
|
3099
|
-
function
|
|
3100
|
-
let
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
let
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
if (cursor === ":") {
|
|
3113
|
-
if (endipv6Encountered === true) {
|
|
3114
|
-
endIpv6 = true;
|
|
3115
|
-
}
|
|
3116
|
-
if (!consume(buffer, address, output)) {
|
|
3117
|
-
break;
|
|
3118
|
-
}
|
|
3119
|
-
if (++tokenCount > 7) {
|
|
3120
|
-
output.error = true;
|
|
3121
|
-
break;
|
|
3122
|
-
}
|
|
3123
|
-
if (i > 0 && input[i - 1] === ":") {
|
|
3124
|
-
endipv6Encountered = true;
|
|
3125
|
-
}
|
|
3126
|
-
address.push(":");
|
|
3127
|
-
continue;
|
|
3128
|
-
} else if (cursor === "%") {
|
|
3129
|
-
if (!consume(buffer, address, output)) {
|
|
3130
|
-
break;
|
|
3117
|
+
function compressIPv6ZeroRun(hextets) {
|
|
3118
|
+
let bestStart = -1;
|
|
3119
|
+
let bestLength = 0;
|
|
3120
|
+
let runStart = -1;
|
|
3121
|
+
let runLength = 0;
|
|
3122
|
+
for (let i = 0;i < hextets.length; i++) {
|
|
3123
|
+
if (hextets[i] === "0") {
|
|
3124
|
+
if (runStart === -1)
|
|
3125
|
+
runStart = i;
|
|
3126
|
+
runLength++;
|
|
3127
|
+
if (runLength > bestLength) {
|
|
3128
|
+
bestLength = runLength;
|
|
3129
|
+
bestStart = runStart;
|
|
3131
3130
|
}
|
|
3132
|
-
consume = consumeIsZone;
|
|
3133
3131
|
} else {
|
|
3134
|
-
|
|
3135
|
-
|
|
3132
|
+
runStart = -1;
|
|
3133
|
+
runLength = 0;
|
|
3136
3134
|
}
|
|
3137
3135
|
}
|
|
3138
|
-
if (
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3136
|
+
if (bestLength < 2)
|
|
3137
|
+
return hextets.join(":");
|
|
3138
|
+
const head = hextets.slice(0, bestStart).join(":");
|
|
3139
|
+
const tail = hextets.slice(bestStart + bestLength).join(":");
|
|
3140
|
+
return head + "::" + tail;
|
|
3141
|
+
}
|
|
3142
|
+
function normalizeIPv6Address(input) {
|
|
3143
|
+
const compression = input.indexOf("::");
|
|
3144
|
+
if (compression !== -1 && input.indexOf("::", compression + 1) !== -1)
|
|
3145
|
+
return;
|
|
3146
|
+
const left = compression === -1 ? input.split(":") : input.slice(0, compression).split(":");
|
|
3147
|
+
const right = compression === -1 ? [] : input.slice(compression + 2).split(":");
|
|
3148
|
+
if (compression !== -1) {
|
|
3149
|
+
if (left.length === 1 && left[0] === "")
|
|
3150
|
+
left.length = 0;
|
|
3151
|
+
if (right.length === 1 && right[0] === "")
|
|
3152
|
+
right.length = 0;
|
|
3153
|
+
}
|
|
3154
|
+
const parts = left.concat(right);
|
|
3155
|
+
let hextetCount = 0;
|
|
3156
|
+
for (let i = 0;i < parts.length; i++) {
|
|
3157
|
+
const part = parts[i];
|
|
3158
|
+
if (part === "")
|
|
3159
|
+
return;
|
|
3160
|
+
if (part.indexOf(".") !== -1) {
|
|
3161
|
+
if (i !== parts.length - 1 || compression !== -1 && right.length === 0 || !isIPv4(part))
|
|
3162
|
+
return;
|
|
3163
|
+
hextetCount += 2;
|
|
3164
|
+
continue;
|
|
3145
3165
|
}
|
|
3166
|
+
if (!isHextet(part))
|
|
3167
|
+
return;
|
|
3168
|
+
parts[i] = parseInt(part, 16).toString(16);
|
|
3169
|
+
hextetCount++;
|
|
3146
3170
|
}
|
|
3147
|
-
|
|
3148
|
-
|
|
3171
|
+
if (compression === -1) {
|
|
3172
|
+
if (hextetCount !== 8)
|
|
3173
|
+
return;
|
|
3174
|
+
return compressIPv6ZeroRun(parts);
|
|
3175
|
+
}
|
|
3176
|
+
if (hextetCount >= 8)
|
|
3177
|
+
return;
|
|
3178
|
+
const expanded = parts.slice(0, left.length);
|
|
3179
|
+
for (let i = hextetCount;i < 8; i++)
|
|
3180
|
+
expanded.push("0");
|
|
3181
|
+
for (let i = left.length;i < parts.length; i++)
|
|
3182
|
+
expanded.push(parts[i]);
|
|
3183
|
+
return compressIPv6ZeroRun(expanded);
|
|
3149
3184
|
}
|
|
3150
3185
|
function normalizeIPv6(host) {
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
}
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3186
|
+
const bracketed = host[0] === "[" && host[host.length - 1] === "]";
|
|
3187
|
+
const hasBracket = host[0] === "[" || host[host.length - 1] === "]";
|
|
3188
|
+
if (hasBracket && !bracketed)
|
|
3189
|
+
return { host, isIPV6: false, error: true };
|
|
3190
|
+
let input = bracketed ? host.slice(1, -1) : host;
|
|
3191
|
+
if (bracketed && isIPvFuture(input)) {
|
|
3192
|
+
input = input.toLowerCase();
|
|
3193
|
+
return { host: `[${input}]`, escapedHost: input, isIPV6: false, isIPVFuture: true };
|
|
3194
|
+
}
|
|
3195
|
+
if (findToken(input, ":") < 2) {
|
|
3196
|
+
return { host, isIPV6: false, error: bracketed };
|
|
3197
|
+
}
|
|
3198
|
+
let zoneIdentifier = "";
|
|
3199
|
+
const zoneSeparator = input.indexOf("%");
|
|
3200
|
+
if (zoneSeparator !== -1) {
|
|
3201
|
+
const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === "%25" ? 3 : 1;
|
|
3202
|
+
zoneIdentifier = input.slice(zoneSeparator + separatorLength);
|
|
3203
|
+
if (!isZoneIdentifier(zoneIdentifier))
|
|
3204
|
+
return { host, isIPV6: false, error: true };
|
|
3205
|
+
input = input.slice(0, zoneSeparator);
|
|
3206
|
+
}
|
|
3207
|
+
const address = normalizeIPv6Address(input);
|
|
3208
|
+
if (address === undefined)
|
|
3209
|
+
return { host, isIPV6: false, error: true };
|
|
3210
|
+
return {
|
|
3211
|
+
host: address + (zoneIdentifier ? "%" + zoneIdentifier : ""),
|
|
3212
|
+
escapedHost: address + (zoneIdentifier ? "%25" + zoneIdentifier : ""),
|
|
3213
|
+
isIPV6: true
|
|
3214
|
+
};
|
|
3166
3215
|
}
|
|
3167
3216
|
function findToken(str, token) {
|
|
3168
3217
|
let ind = 0;
|
|
@@ -3282,7 +3331,8 @@ var require_utils = __commonJS(function(exports, module) {
|
|
|
3282
3331
|
function normalizePathEncoding(input) {
|
|
3283
3332
|
let output = "";
|
|
3284
3333
|
for (let i = 0;i < input.length; i++) {
|
|
3285
|
-
|
|
3334
|
+
const ch = input[i];
|
|
3335
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3286
3336
|
const hex3 = input.slice(i + 1, i + 3);
|
|
3287
3337
|
if (isHexPair(hex3)) {
|
|
3288
3338
|
const normalizedHex = hex3.toUpperCase();
|
|
@@ -3296,10 +3346,152 @@ var require_utils = __commonJS(function(exports, module) {
|
|
|
3296
3346
|
continue;
|
|
3297
3347
|
}
|
|
3298
3348
|
}
|
|
3299
|
-
if (isPathCharacter(
|
|
3300
|
-
output +=
|
|
3349
|
+
if (isPathCharacter(ch)) {
|
|
3350
|
+
output += ch;
|
|
3301
3351
|
} else {
|
|
3302
|
-
|
|
3352
|
+
const code = input.charCodeAt(i);
|
|
3353
|
+
if (code < 128) {
|
|
3354
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3355
|
+
} else if (code < 55296 || code > 57343) {
|
|
3356
|
+
output += percentEncodeNonAscii(code);
|
|
3357
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3358
|
+
const low = input.charCodeAt(i + 1);
|
|
3359
|
+
if (low >= 56320 && low <= 57343) {
|
|
3360
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3361
|
+
i++;
|
|
3362
|
+
} else {
|
|
3363
|
+
output += percentEncodeNonAscii(65533);
|
|
3364
|
+
}
|
|
3365
|
+
} else {
|
|
3366
|
+
output += percentEncodeNonAscii(65533);
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
}
|
|
3370
|
+
return output;
|
|
3371
|
+
}
|
|
3372
|
+
function serializePathEncoding(input, pathNoScheme = false) {
|
|
3373
|
+
let output = "";
|
|
3374
|
+
let firstSegment = pathNoScheme && input[0] !== "/";
|
|
3375
|
+
for (let i = 0;i < input.length; i++) {
|
|
3376
|
+
const ch = input[i];
|
|
3377
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3378
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3379
|
+
if (isHexPair(hex3)) {
|
|
3380
|
+
output += "%" + hex3.toUpperCase();
|
|
3381
|
+
i += 2;
|
|
3382
|
+
continue;
|
|
3383
|
+
}
|
|
3384
|
+
}
|
|
3385
|
+
if (ch === "/") {
|
|
3386
|
+
firstSegment = false;
|
|
3387
|
+
}
|
|
3388
|
+
if (isPathCharacter(ch) && (ch !== ":" || !firstSegment)) {
|
|
3389
|
+
output += ch;
|
|
3390
|
+
} else {
|
|
3391
|
+
const code = input.charCodeAt(i);
|
|
3392
|
+
if (code < 128) {
|
|
3393
|
+
output += BYTE_HEX[code];
|
|
3394
|
+
} else if (code < 55296 || code > 57343) {
|
|
3395
|
+
output += percentEncodeNonAscii(code);
|
|
3396
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3397
|
+
const low = input.charCodeAt(i + 1);
|
|
3398
|
+
if (low >= 56320 && low <= 57343) {
|
|
3399
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3400
|
+
i++;
|
|
3401
|
+
} else {
|
|
3402
|
+
output += percentEncodeNonAscii(65533);
|
|
3403
|
+
}
|
|
3404
|
+
} else {
|
|
3405
|
+
output += percentEncodeNonAscii(65533);
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
return output;
|
|
3410
|
+
}
|
|
3411
|
+
function encodeComponent(input, isAllowed) {
|
|
3412
|
+
let output = "";
|
|
3413
|
+
for (let i = 0;i < input.length; i++) {
|
|
3414
|
+
const ch = input[i];
|
|
3415
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3416
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3417
|
+
if (isHexPair(hex3)) {
|
|
3418
|
+
output += "%" + hex3.toUpperCase();
|
|
3419
|
+
i += 2;
|
|
3420
|
+
continue;
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
if (isAllowed(ch)) {
|
|
3424
|
+
output += ch;
|
|
3425
|
+
} else {
|
|
3426
|
+
const code = input.charCodeAt(i);
|
|
3427
|
+
if (code < 128) {
|
|
3428
|
+
output += BYTE_HEX[code];
|
|
3429
|
+
} else if (code < 55296 || code > 57343) {
|
|
3430
|
+
output += percentEncodeNonAscii(code);
|
|
3431
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3432
|
+
const low = input.charCodeAt(i + 1);
|
|
3433
|
+
if (low >= 56320 && low <= 57343) {
|
|
3434
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3435
|
+
i++;
|
|
3436
|
+
} else {
|
|
3437
|
+
output += percentEncodeNonAscii(65533);
|
|
3438
|
+
}
|
|
3439
|
+
} else {
|
|
3440
|
+
output += percentEncodeNonAscii(65533);
|
|
3441
|
+
}
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3444
|
+
return output;
|
|
3445
|
+
}
|
|
3446
|
+
function encodeUserinfo(input) {
|
|
3447
|
+
return encodeComponent(input, isUserinfoCharacter);
|
|
3448
|
+
}
|
|
3449
|
+
function encodeQuery(input) {
|
|
3450
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3451
|
+
}
|
|
3452
|
+
function encodeFragment(input) {
|
|
3453
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3454
|
+
}
|
|
3455
|
+
function isEscapeSafe(cp) {
|
|
3456
|
+
return cp >= 48 && cp <= 57 || cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp === 42 || cp === 43 || cp === 45 || cp === 46 || cp === 47 || cp === 64 || cp === 95;
|
|
3457
|
+
}
|
|
3458
|
+
function normalizeQueryFragmentEncoding(input) {
|
|
3459
|
+
let output = "";
|
|
3460
|
+
for (let i = 0;i < input.length; i++) {
|
|
3461
|
+
const ch = input[i];
|
|
3462
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3463
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3464
|
+
if (isHexPair(hex3)) {
|
|
3465
|
+
const normalizedHex = hex3.toUpperCase();
|
|
3466
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
3467
|
+
if (isUnreserved(decoded)) {
|
|
3468
|
+
output += decoded;
|
|
3469
|
+
} else {
|
|
3470
|
+
output += "%" + normalizedHex;
|
|
3471
|
+
}
|
|
3472
|
+
i += 2;
|
|
3473
|
+
continue;
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
if (isQueryFragmentCharacter(ch)) {
|
|
3477
|
+
output += ch;
|
|
3478
|
+
} else {
|
|
3479
|
+
const code = input.charCodeAt(i);
|
|
3480
|
+
if (code < 128) {
|
|
3481
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3482
|
+
} else if (code < 55296 || code > 57343) {
|
|
3483
|
+
output += percentEncodeNonAscii(code);
|
|
3484
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3485
|
+
const low = input.charCodeAt(i + 1);
|
|
3486
|
+
if (low >= 56320 && low <= 57343) {
|
|
3487
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3488
|
+
i++;
|
|
3489
|
+
} else {
|
|
3490
|
+
output += percentEncodeNonAscii(65533);
|
|
3491
|
+
}
|
|
3492
|
+
} else {
|
|
3493
|
+
output += percentEncodeNonAscii(65533);
|
|
3494
|
+
}
|
|
3303
3495
|
}
|
|
3304
3496
|
}
|
|
3305
3497
|
return output;
|
|
@@ -3322,14 +3514,18 @@ var require_utils = __commonJS(function(exports, module) {
|
|
|
3322
3514
|
function recomposeAuthority(component) {
|
|
3323
3515
|
const uriTokens = [];
|
|
3324
3516
|
if (component.userinfo !== undefined) {
|
|
3325
|
-
uriTokens.push(component.userinfo);
|
|
3517
|
+
uriTokens.push(encodeUserinfo(component.userinfo));
|
|
3326
3518
|
uriTokens.push("@");
|
|
3327
3519
|
}
|
|
3328
3520
|
if (component.host !== undefined) {
|
|
3329
|
-
let host =
|
|
3521
|
+
let host = component.host;
|
|
3330
3522
|
if (!isIPv4(host)) {
|
|
3331
|
-
|
|
3332
|
-
if (ipV6res.isIPV6
|
|
3523
|
+
let ipV6res = normalizeIPv6(host);
|
|
3524
|
+
if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
|
|
3525
|
+
host = normalizePercentEncoding(host, true);
|
|
3526
|
+
ipV6res = normalizeIPv6(host);
|
|
3527
|
+
}
|
|
3528
|
+
if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) {
|
|
3333
3529
|
host = `[${ipV6res.escapedHost}]`;
|
|
3334
3530
|
} else {
|
|
3335
3531
|
host = reescapeHostDelimiters(host, false);
|
|
@@ -3349,6 +3545,11 @@ var require_utils = __commonJS(function(exports, module) {
|
|
|
3349
3545
|
reescapeHostDelimiters,
|
|
3350
3546
|
normalizePercentEncoding,
|
|
3351
3547
|
normalizePathEncoding,
|
|
3548
|
+
serializePathEncoding,
|
|
3549
|
+
normalizeQueryFragmentEncoding,
|
|
3550
|
+
encodeUserinfo,
|
|
3551
|
+
encodeQuery,
|
|
3552
|
+
encodeFragment,
|
|
3352
3553
|
escapePreservingEscapes,
|
|
3353
3554
|
removeDotSegments,
|
|
3354
3555
|
isIPv4,
|
|
@@ -3361,7 +3562,7 @@ var require_utils = __commonJS(function(exports, module) {
|
|
|
3361
3562
|
// node_modules/fast-uri/lib/schemes.js
|
|
3362
3563
|
var require_schemes = __commonJS(function(exports, module) {
|
|
3363
3564
|
var { isUUID } = require_utils();
|
|
3364
|
-
var URN_REG =
|
|
3565
|
+
var URN_REG = /^([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-./:;=@]|%[\da-f]{2})+)$/iu;
|
|
3365
3566
|
var supportedSchemeNames = [
|
|
3366
3567
|
"http",
|
|
3367
3568
|
"https",
|
|
@@ -3416,9 +3617,10 @@ var require_schemes = __commonJS(function(exports, module) {
|
|
|
3416
3617
|
wsComponent.secure = undefined;
|
|
3417
3618
|
}
|
|
3418
3619
|
if (wsComponent.resourceName) {
|
|
3419
|
-
const
|
|
3620
|
+
const queryIndex = wsComponent.resourceName.indexOf("?");
|
|
3621
|
+
const path = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
|
|
3420
3622
|
wsComponent.path = path && path !== "/" ? path : undefined;
|
|
3421
|
-
wsComponent.query =
|
|
3623
|
+
wsComponent.query = queryIndex === -1 ? undefined : wsComponent.resourceName.slice(queryIndex + 1);
|
|
3422
3624
|
wsComponent.resourceName = undefined;
|
|
3423
3625
|
}
|
|
3424
3626
|
wsComponent.fragment = undefined;
|
|
@@ -3430,7 +3632,7 @@ var require_schemes = __commonJS(function(exports, module) {
|
|
|
3430
3632
|
return urnComponent;
|
|
3431
3633
|
}
|
|
3432
3634
|
const matches = urnComponent.path.match(URN_REG);
|
|
3433
|
-
if (matches) {
|
|
3635
|
+
if (matches && matches[0] === urnComponent.path) {
|
|
3434
3636
|
const scheme = options.scheme || urnComponent.scheme || "urn";
|
|
3435
3637
|
urnComponent.nid = matches[1].toLowerCase();
|
|
3436
3638
|
urnComponent.nss = matches[2];
|
|
@@ -3534,8 +3736,17 @@ var require_schemes = __commonJS(function(exports, module) {
|
|
|
3534
3736
|
|
|
3535
3737
|
// node_modules/fast-uri/index.js
|
|
3536
3738
|
var require_fast_uri = __commonJS(function(exports, module) {
|
|
3537
|
-
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding,
|
|
3739
|
+
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3538
3740
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
3741
|
+
var VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
3742
|
+
var MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
|
|
3743
|
+
function decodeValidScheme(scheme) {
|
|
3744
|
+
const decodedScheme = unescape(String(scheme));
|
|
3745
|
+
if (!VALID_SCHEME.test(decodedScheme)) {
|
|
3746
|
+
throw new TypeError(MALFORMED_SCHEME_ERROR);
|
|
3747
|
+
}
|
|
3748
|
+
return decodedScheme;
|
|
3749
|
+
}
|
|
3539
3750
|
function normalize(uri, options) {
|
|
3540
3751
|
if (typeof uri === "string") {
|
|
3541
3752
|
uri = normalizeString(uri, options);
|
|
@@ -3546,12 +3757,34 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3546
3757
|
}
|
|
3547
3758
|
function resolve(baseURI, relativeURI, options) {
|
|
3548
3759
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3549
|
-
const {
|
|
3550
|
-
|
|
3551
|
-
|
|
3760
|
+
const {
|
|
3761
|
+
parsed: baseParsed,
|
|
3762
|
+
malformedAuthorityOrPort: baseMalformed,
|
|
3763
|
+
malformedPercentEncoding: baseMalformedPercentEncoding,
|
|
3764
|
+
malformedSchemeSpecific: baseMalformedSchemeSpecific,
|
|
3765
|
+
malformedHost: baseMalformedHost,
|
|
3766
|
+
malformedScheme: baseMalformedScheme
|
|
3767
|
+
} = parseWithStatus(baseURI, schemelessOptions);
|
|
3768
|
+
const {
|
|
3769
|
+
parsed: relativeParsed,
|
|
3770
|
+
malformedAuthorityOrPort: relativeMalformed,
|
|
3771
|
+
malformedPercentEncoding: relativeMalformedPercentEncoding,
|
|
3772
|
+
malformedSchemeSpecific: relativeMalformedSchemeSpecific,
|
|
3773
|
+
malformedHost: relativeMalformedHost,
|
|
3774
|
+
malformedScheme: relativeMalformedScheme
|
|
3775
|
+
} = parseWithStatus(relativeURI, schemelessOptions);
|
|
3776
|
+
if (baseMalformed || relativeMalformed || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) {
|
|
3552
3777
|
throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
|
|
3553
3778
|
}
|
|
3554
3779
|
const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
|
|
3780
|
+
const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
|
|
3781
|
+
const resolvedHost = resolved.host;
|
|
3782
|
+
const resolvedHostIsIP = resolvedHost !== undefined && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
|
|
3783
|
+
canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
|
|
3784
|
+
const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !/\P{ASCII}/u.test(resolvedHost);
|
|
3785
|
+
if (resolved.error && !encodedASCIIHost) {
|
|
3786
|
+
throw new Error(resolved.error);
|
|
3787
|
+
}
|
|
3555
3788
|
schemelessOptions.skipEscape = true;
|
|
3556
3789
|
return serialize(resolved, schemelessOptions);
|
|
3557
3790
|
}
|
|
@@ -3611,7 +3844,7 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3611
3844
|
function equal(uriA, uriB, options) {
|
|
3612
3845
|
const normalizedA = normalizeComparableURI(uriA, options);
|
|
3613
3846
|
const normalizedB = normalizeComparableURI(uriB, options);
|
|
3614
|
-
return normalizedA !== undefined && normalizedB !== undefined && normalizedA
|
|
3847
|
+
return normalizedA !== undefined && normalizedB !== undefined && normalizedA === normalizedB;
|
|
3615
3848
|
}
|
|
3616
3849
|
function serialize(cmpts, opts) {
|
|
3617
3850
|
const component = {
|
|
@@ -3632,20 +3865,23 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3632
3865
|
};
|
|
3633
3866
|
const options = Object.assign({}, opts);
|
|
3634
3867
|
const uriTokens = [];
|
|
3868
|
+
if (component.scheme) {
|
|
3869
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3870
|
+
}
|
|
3635
3871
|
const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
|
|
3636
3872
|
if (schemeHandler && schemeHandler.serialize)
|
|
3637
3873
|
schemeHandler.serialize(component, options);
|
|
3874
|
+
const hasAuthority = component.userinfo !== undefined || component.host !== undefined || component.port !== undefined;
|
|
3875
|
+
const pathNoScheme = !options.skipEscape && component.scheme === undefined && !hasAuthority;
|
|
3638
3876
|
if (component.path !== undefined) {
|
|
3639
3877
|
if (!options.skipEscape) {
|
|
3640
|
-
component.path =
|
|
3641
|
-
if (component.scheme !== undefined) {
|
|
3642
|
-
component.path = component.path.split("%3A").join(":");
|
|
3643
|
-
}
|
|
3878
|
+
component.path = serializePathEncoding(component.path, pathNoScheme);
|
|
3644
3879
|
} else {
|
|
3645
3880
|
component.path = normalizePercentEncoding(component.path);
|
|
3646
3881
|
}
|
|
3647
3882
|
}
|
|
3648
3883
|
if (options.reference !== "suffix" && component.scheme) {
|
|
3884
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3649
3885
|
uriTokens.push(component.scheme, ":");
|
|
3650
3886
|
}
|
|
3651
3887
|
const authority = recomposeAuthority(component);
|
|
@@ -3663,16 +3899,19 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3663
3899
|
if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
|
|
3664
3900
|
s = removeDotSegments(s);
|
|
3665
3901
|
}
|
|
3902
|
+
if (pathNoScheme) {
|
|
3903
|
+
s = serializePathEncoding(s, true);
|
|
3904
|
+
}
|
|
3666
3905
|
if (authority === undefined && s[0] === "/" && s[1] === "/") {
|
|
3667
3906
|
s = "/%2F" + s.slice(2);
|
|
3668
3907
|
}
|
|
3669
3908
|
uriTokens.push(s);
|
|
3670
3909
|
}
|
|
3671
3910
|
if (component.query !== undefined) {
|
|
3672
|
-
uriTokens.push("?", component.query);
|
|
3911
|
+
uriTokens.push("?", encodeQuery(component.query));
|
|
3673
3912
|
}
|
|
3674
3913
|
if (component.fragment !== undefined) {
|
|
3675
|
-
uriTokens.push("#", component.fragment);
|
|
3914
|
+
uriTokens.push("#", encodeFragment(component.fragment));
|
|
3676
3915
|
}
|
|
3677
3916
|
return uriTokens.join("");
|
|
3678
3917
|
}
|
|
@@ -3688,6 +3927,33 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3688
3927
|
}
|
|
3689
3928
|
return;
|
|
3690
3929
|
}
|
|
3930
|
+
function hasMalformedPercentEncoding(component) {
|
|
3931
|
+
if (component === undefined)
|
|
3932
|
+
return false;
|
|
3933
|
+
let percent = component.indexOf("%");
|
|
3934
|
+
while (percent !== -1) {
|
|
3935
|
+
if (percent + 2 >= component.length || !/^[\da-f]{2}$/iu.test(component.slice(percent + 1, percent + 3))) {
|
|
3936
|
+
return true;
|
|
3937
|
+
}
|
|
3938
|
+
percent = component.indexOf("%", percent + 3);
|
|
3939
|
+
}
|
|
3940
|
+
return false;
|
|
3941
|
+
}
|
|
3942
|
+
function hasMalformedComponentPercentEncoding(matches) {
|
|
3943
|
+
const host = matches[4];
|
|
3944
|
+
return hasMalformedPercentEncoding(matches[3]) || host !== undefined && !(host[0] === "[" && host[host.length - 1] === "]") && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
|
|
3945
|
+
}
|
|
3946
|
+
function canonicalizeHost(parsed, options, schemeHandler, isIP) {
|
|
3947
|
+
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && parsed.host[0] !== "[" && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
|
|
3948
|
+
try {
|
|
3949
|
+
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
3950
|
+
} catch (e) {
|
|
3951
|
+
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
3952
|
+
return true;
|
|
3953
|
+
}
|
|
3954
|
+
}
|
|
3955
|
+
return false;
|
|
3956
|
+
}
|
|
3691
3957
|
function parseWithStatus(uri, opts) {
|
|
3692
3958
|
const options = Object.assign({}, opts);
|
|
3693
3959
|
const parsed = {
|
|
@@ -3700,6 +3966,11 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3700
3966
|
fragment: undefined
|
|
3701
3967
|
};
|
|
3702
3968
|
let malformedAuthorityOrPort = false;
|
|
3969
|
+
let malformedPercentEncoding = false;
|
|
3970
|
+
let malformedSchemeSpecific = false;
|
|
3971
|
+
let malformedHost = false;
|
|
3972
|
+
let malformedIPLiteral = false;
|
|
3973
|
+
let malformedScheme = false;
|
|
3703
3974
|
let isIP = false;
|
|
3704
3975
|
if (options.reference === "suffix") {
|
|
3705
3976
|
if (options.scheme) {
|
|
@@ -3736,6 +4007,19 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3736
4007
|
parsed.path = matches[6] || "";
|
|
3737
4008
|
parsed.query = matches[7];
|
|
3738
4009
|
parsed.fragment = matches[8];
|
|
4010
|
+
if (parsed.scheme !== undefined) {
|
|
4011
|
+
const decodedScheme = unescape(parsed.scheme);
|
|
4012
|
+
if (VALID_SCHEME.test(decodedScheme)) {
|
|
4013
|
+
parsed.scheme = decodedScheme.toLowerCase();
|
|
4014
|
+
} else {
|
|
4015
|
+
parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
|
|
4016
|
+
malformedScheme = true;
|
|
4017
|
+
}
|
|
4018
|
+
}
|
|
4019
|
+
malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches);
|
|
4020
|
+
if (malformedPercentEncoding) {
|
|
4021
|
+
parsed.error = parsed.error || "URI contains malformed percent-encoding.";
|
|
4022
|
+
}
|
|
3739
4023
|
if (isNaN(parsed.port)) {
|
|
3740
4024
|
parsed.port = matches[5];
|
|
3741
4025
|
}
|
|
@@ -3747,9 +4031,15 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3747
4031
|
if (parsed.host) {
|
|
3748
4032
|
const ipv4result = isIPv4(parsed.host);
|
|
3749
4033
|
if (ipv4result === false) {
|
|
4034
|
+
const bracketedIPLiteral = parsed.host[0] === "[" && parsed.host[parsed.host.length - 1] === "]";
|
|
3750
4035
|
const ipv6result = normalizeIPv6(parsed.host);
|
|
3751
|
-
|
|
3752
|
-
|
|
4036
|
+
isIP = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
|
|
4037
|
+
malformedIPLiteral = bracketedIPLiteral && ipv6result.error === true;
|
|
4038
|
+
parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
|
|
4039
|
+
if (malformedIPLiteral) {
|
|
4040
|
+
parsed.error = parsed.error || "URI host is malformed.";
|
|
4041
|
+
malformedAuthorityOrPort = true;
|
|
4042
|
+
}
|
|
3753
4043
|
} else {
|
|
3754
4044
|
isIP = true;
|
|
3755
4045
|
}
|
|
@@ -3767,42 +4057,34 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3767
4057
|
parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
|
|
3768
4058
|
}
|
|
3769
4059
|
const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
|
|
3770
|
-
|
|
3771
|
-
if (parsed.host && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
|
|
3772
|
-
try {
|
|
3773
|
-
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
3774
|
-
} catch (e) {
|
|
3775
|
-
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
3776
|
-
}
|
|
3777
|
-
}
|
|
3778
|
-
}
|
|
4060
|
+
malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
|
|
3779
4061
|
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
3780
4062
|
if (uri.indexOf("%") !== -1) {
|
|
3781
|
-
if (parsed.
|
|
3782
|
-
parsed.
|
|
3783
|
-
|
|
3784
|
-
if (parsed.host !== undefined) {
|
|
3785
|
-
parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
|
|
4063
|
+
if (parsed.host !== undefined && !malformedIPLiteral) {
|
|
4064
|
+
const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
|
|
4065
|
+
parsed.host = reescapeHostDelimiters(host, isIP);
|
|
3786
4066
|
}
|
|
3787
4067
|
}
|
|
3788
4068
|
if (parsed.path) {
|
|
3789
4069
|
parsed.path = normalizePathEncoding(parsed.path);
|
|
3790
4070
|
}
|
|
4071
|
+
if (parsed.query) {
|
|
4072
|
+
parsed.query = normalizeQueryFragmentEncoding(parsed.query);
|
|
4073
|
+
}
|
|
3791
4074
|
if (parsed.fragment) {
|
|
3792
|
-
|
|
3793
|
-
parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
|
|
3794
|
-
} catch {
|
|
3795
|
-
parsed.error = parsed.error || "URI malformed";
|
|
3796
|
-
}
|
|
4075
|
+
parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment);
|
|
3797
4076
|
}
|
|
3798
4077
|
}
|
|
3799
4078
|
if (schemeHandler && schemeHandler.parse) {
|
|
3800
4079
|
schemeHandler.parse(parsed, options);
|
|
4080
|
+
if (schemeHandler === SCHEMES.urn && parsed.nid === undefined) {
|
|
4081
|
+
malformedSchemeSpecific = true;
|
|
4082
|
+
}
|
|
3801
4083
|
}
|
|
3802
4084
|
} else {
|
|
3803
4085
|
parsed.error = parsed.error || "URI can not be parsed.";
|
|
3804
4086
|
}
|
|
3805
|
-
return { parsed, malformedAuthorityOrPort };
|
|
4087
|
+
return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
|
|
3806
4088
|
}
|
|
3807
4089
|
function parse6(uri, opts) {
|
|
3808
4090
|
return parseWithStatus(uri, opts).parsed;
|
|
@@ -3811,20 +4093,28 @@ var require_fast_uri = __commonJS(function(exports, module) {
|
|
|
3811
4093
|
return normalizeStringWithStatus(uri, opts).normalized;
|
|
3812
4094
|
}
|
|
3813
4095
|
function normalizeStringWithStatus(uri, opts) {
|
|
3814
|
-
const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
|
|
4096
|
+
const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
|
|
3815
4097
|
return {
|
|
3816
|
-
normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
|
|
3817
|
-
malformedAuthorityOrPort
|
|
4098
|
+
normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
|
|
4099
|
+
malformedAuthorityOrPort,
|
|
4100
|
+
malformedPercentEncoding,
|
|
4101
|
+
malformedSchemeSpecific,
|
|
4102
|
+
malformedHost,
|
|
4103
|
+
malformedScheme
|
|
3818
4104
|
};
|
|
3819
4105
|
}
|
|
3820
4106
|
function normalizeComparableURI(uri, opts) {
|
|
3821
|
-
if (typeof uri
|
|
3822
|
-
|
|
3823
|
-
return malformedAuthorityOrPort ? undefined : normalized;
|
|
4107
|
+
if (typeof uri !== "string" && typeof uri !== "object") {
|
|
4108
|
+
return;
|
|
3824
4109
|
}
|
|
3825
|
-
|
|
3826
|
-
|
|
4110
|
+
let value;
|
|
4111
|
+
try {
|
|
4112
|
+
value = typeof uri === "string" ? uri : serialize(uri, opts);
|
|
4113
|
+
} catch {
|
|
4114
|
+
return;
|
|
3827
4115
|
}
|
|
4116
|
+
const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
|
|
4117
|
+
return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? undefined : normalized;
|
|
3828
4118
|
}
|
|
3829
4119
|
var fastUri = {
|
|
3830
4120
|
SCHEMES,
|
|
@@ -29434,6 +29724,9 @@ function agentToReviewLayer(agent) {
|
|
|
29434
29724
|
return "quality";
|
|
29435
29725
|
return;
|
|
29436
29726
|
}
|
|
29727
|
+
function isReviewerFamily(agent) {
|
|
29728
|
+
return agent === "openspec-architect" || agentToReviewLayer(agent) !== undefined;
|
|
29729
|
+
}
|
|
29437
29730
|
function readIssueSource(child) {
|
|
29438
29731
|
return typeof child.metadata["source"] === "string" ? child.metadata["source"] : undefined;
|
|
29439
29732
|
}
|
|
@@ -29719,6 +30012,39 @@ async function reconcileMainPollution(mainRepo, worktreePath, opts) {
|
|
|
29719
30012
|
}
|
|
29720
30013
|
}
|
|
29721
30014
|
}
|
|
30015
|
+
async function autoCommitWorktreeChanges(wtPath, agent, stepId) {
|
|
30016
|
+
const statusRes = await runGitChecked(wtPath, ["status", "--porcelain"]);
|
|
30017
|
+
if (!statusRes.success) {
|
|
30018
|
+
return { status: "failed", files: [], untrackedFiles: [], stderr: statusRes.stderr };
|
|
30019
|
+
}
|
|
30020
|
+
const files = [];
|
|
30021
|
+
const untrackedFiles = [];
|
|
30022
|
+
for (const line of statusRes.stdout.split(`
|
|
30023
|
+
`).map((l) => l.trim()).filter(Boolean)) {
|
|
30024
|
+
const path2 = parsePorcelainPaths(line)[0];
|
|
30025
|
+
if (!path2 || path2.startsWith("openspec/states/"))
|
|
30026
|
+
continue;
|
|
30027
|
+
if (line.startsWith("??"))
|
|
30028
|
+
untrackedFiles.push(path2);
|
|
30029
|
+
else
|
|
30030
|
+
files.push(path2);
|
|
30031
|
+
}
|
|
30032
|
+
if (files.length === 0)
|
|
30033
|
+
return { status: "skipped", files: [], untrackedFiles };
|
|
30034
|
+
const addResult = await runGitChecked(wtPath, ["add", "-u", "--", ".", ":(exclude)openspec/states"]);
|
|
30035
|
+
if (!addResult.success) {
|
|
30036
|
+
return { status: "failed", files, untrackedFiles, stderr: addResult.stderr };
|
|
30037
|
+
}
|
|
30038
|
+
const commitResult = await runGitChecked(wtPath, [
|
|
30039
|
+
"commit",
|
|
30040
|
+
"-m",
|
|
30041
|
+
`docs(opx): direct fixes by ${agent} (${stepId})`
|
|
30042
|
+
]);
|
|
30043
|
+
if (!commitResult.success) {
|
|
30044
|
+
return { status: "failed", files, untrackedFiles, stderr: commitResult.stderr };
|
|
30045
|
+
}
|
|
30046
|
+
return { status: "committed", files, untrackedFiles };
|
|
30047
|
+
}
|
|
29722
30048
|
|
|
29723
30049
|
// src/core/state.ts
|
|
29724
30050
|
import path2 from "path";
|
|
@@ -34624,6 +34950,20 @@ function renderAgentSummaries(agentSummaries, agentName) {
|
|
|
34624
34950
|
lines.push("");
|
|
34625
34951
|
return lines;
|
|
34626
34952
|
}
|
|
34953
|
+
function renderDevSelfCheckDeclaration(metadata) {
|
|
34954
|
+
const selfCheck = typeof metadata["self_check_results"] === "string" ? metadata["self_check_results"].trim() : "";
|
|
34955
|
+
const testResults = typeof metadata["test_results"] === "string" ? metadata["test_results"].trim() : "";
|
|
34956
|
+
if (selfCheck === "" && testResults === "")
|
|
34957
|
+
return [];
|
|
34958
|
+
const lines = ["## 开发者自检申报", ""];
|
|
34959
|
+
if (selfCheck !== "") {
|
|
34960
|
+
lines.push("**自检申报(self_check_results)**:", "", selfCheck, "");
|
|
34961
|
+
}
|
|
34962
|
+
if (testResults !== "") {
|
|
34963
|
+
lines.push("**接口测试结果(test_results)**:", "", testResults, "");
|
|
34964
|
+
}
|
|
34965
|
+
return lines;
|
|
34966
|
+
}
|
|
34627
34967
|
var INTERPOLATION_ALLOWED_KEYS = new Set([
|
|
34628
34968
|
"worktree_path",
|
|
34629
34969
|
"change_id",
|
|
@@ -35156,7 +35496,13 @@ function renderAgentWorking(item, rec, step, common2, ctxAgent, state, tg, toolC
|
|
|
35156
35496
|
lines.push(...renderStepSemantics(step, common2, stepCtx));
|
|
35157
35497
|
lines.push(...renderWorktreeSection(state, tg, { showNamespace: true, showPort: true }));
|
|
35158
35498
|
if (step?.id === "verify_tool" && agentToReviewLayer(ctxAgent) === "tool" && toolChanges?.hasNonDocChange) {
|
|
35159
|
-
lines.push(...renderToolChangesEvidence(item, tg, toolChanges));
|
|
35499
|
+
lines.push(...renderToolChangesEvidence(item, tg, toolChanges, "tool_review"));
|
|
35500
|
+
}
|
|
35501
|
+
if (step?.id === "quality_review" && toolChanges) {
|
|
35502
|
+
lines.push(...renderToolChangesEvidence(item, tg, toolChanges, "merged_review"));
|
|
35503
|
+
}
|
|
35504
|
+
if (step?.id === "quality_review") {
|
|
35505
|
+
lines.push(...renderDevSelfCheckDeclaration(item.metadata));
|
|
35160
35506
|
}
|
|
35161
35507
|
lines.push(...renderAgentSummaries(readAgentSummaries(item), ctxAgent));
|
|
35162
35508
|
lines.push(...renderStepContext(item, step, ctxAgent, state, exemptionCtx));
|
|
@@ -35364,15 +35710,20 @@ function renderToolChildren(item, ctxAgent, exemptionCtx) {
|
|
|
35364
35710
|
lines.push(...renderChildrenSection("Issue (待裁定是否可豁免)", pending, exemptionCtx));
|
|
35365
35711
|
return lines;
|
|
35366
35712
|
}
|
|
35367
|
-
|
|
35713
|
+
var EVIDENCE_KIND_LABELS = {
|
|
35714
|
+
tool_review: { title: "自上次工具检查", lastCheck: "上次工具检查" },
|
|
35715
|
+
merged_review: { title: "自上次合并审查", lastCheck: "上次合并审查" }
|
|
35716
|
+
};
|
|
35717
|
+
function renderToolChangesEvidence(item, tg, toolChanges, kind) {
|
|
35718
|
+
const label = EVIDENCE_KIND_LABELS[kind];
|
|
35368
35719
|
const checkpoint = typeof item.metadata["_tool_review_checkpoint"] === "string" ? item.metadata["_tool_review_checkpoint"] : undefined;
|
|
35369
35720
|
const baseRef = tg.baseRef ?? undefined;
|
|
35370
35721
|
const rangeRef = checkpoint ?? baseRef;
|
|
35371
|
-
const lines = [
|
|
35722
|
+
const lines = [`## 本次变更证据(${label.title})`, ""];
|
|
35372
35723
|
if (checkpoint) {
|
|
35373
|
-
lines.push(`- **口径**:
|
|
35724
|
+
lines.push(`- **口径**: 本次为「${label.title}(${checkpoint}..HEAD)」的增量区间(含已提交与未提交的非 openspec 变更);` + `与上方「变更范围」(${baseRef ?? "(无)"}..HEAD 整个 change 累计口径)不同`, "");
|
|
35374
35725
|
} else if (baseRef) {
|
|
35375
|
-
lines.push(`- **口径**: 本次区间以基线(${baseRef}..HEAD
|
|
35726
|
+
lines.push(`- **口径**: 本次区间以基线(${baseRef}..HEAD)兜底,与上方「变更范围」一致(首次进入,无${label.lastCheck}记录;` + "含已提交与未提交的非 openspec 变更)", "");
|
|
35376
35727
|
} else {
|
|
35377
35728
|
lines.push("- **口径**: 无检查点且无基线基准,无法界定已提交变更区间;本次变更仅按检出文件与未提交变更提示", "");
|
|
35378
35729
|
}
|
|
@@ -36035,7 +36386,8 @@ async function statusExecute(params, ctx) {
|
|
|
36035
36386
|
const tg = findTaskGroup(state, state.taskGroupId);
|
|
36036
36387
|
const mainPollution = ctx.orchestrator ? await detectMainRepoPollution(ctx.worktree) : null;
|
|
36037
36388
|
let toolChanges;
|
|
36038
|
-
|
|
36389
|
+
const changesEvidenceStep = rec.status === "recommend" && rec.agents.includes(agent) && (agentToReviewLayer(agent) === "tool" && rec.stepId === "verify_tool" || agent === "openspec-reviewer" && rec.stepId === "quality_review");
|
|
36390
|
+
if (changesEvidenceStep) {
|
|
36039
36391
|
const wtPath = typeof item.metadata["worktree_path"] === "string" ? item.metadata["worktree_path"] : undefined;
|
|
36040
36392
|
if (wtPath) {
|
|
36041
36393
|
const checkpoint = typeof item.metadata["_tool_review_checkpoint"] === "string" ? item.metadata["_tool_review_checkpoint"] : undefined;
|
|
@@ -36314,6 +36666,9 @@ function handleImplementParams(item, params) {
|
|
|
36314
36666
|
if (params.self_check_results) {
|
|
36315
36667
|
item.metadata["self_check_results"] = params.self_check_results;
|
|
36316
36668
|
}
|
|
36669
|
+
if (params.test_results) {
|
|
36670
|
+
item.metadata["test_results"] = params.test_results;
|
|
36671
|
+
}
|
|
36317
36672
|
}
|
|
36318
36673
|
function mergeBoundaryInto(item, expansion) {
|
|
36319
36674
|
const boundary = item.metadata["execution_boundary"];
|
|
@@ -36365,7 +36720,7 @@ function handleReviewParams(item, params, newChildren, stepId, opts) {
|
|
|
36365
36720
|
}
|
|
36366
36721
|
mergeBoundaryInto(item, params.boundary_expansion);
|
|
36367
36722
|
}
|
|
36368
|
-
if (params.test_results)
|
|
36723
|
+
if (params.test_results && stepId !== "quality_review")
|
|
36369
36724
|
item.metadata["test_results"] = params.test_results;
|
|
36370
36725
|
if (params.validation_steps) {
|
|
36371
36726
|
assertStructuredSkipReasons(params.validation_steps);
|
|
@@ -36375,7 +36730,7 @@ function handleReviewParams(item, params, newChildren, stepId, opts) {
|
|
|
36375
36730
|
const uncovered = uncoveredMustDo(opts.capabilityTags, params.validation_steps);
|
|
36376
36731
|
if (uncovered.length > 0) {
|
|
36377
36732
|
throw new Error(`提交的验证步骤未覆盖质量门 skill 必做清单,缺少以下必做项:${uncovered.join("、")}。
|
|
36378
|
-
` + `请按已加载质量门类 skill 的必做清单逐项执行并逐项申报结果(completed=true);` + `确实无法执行的必做项须以结构化 skip_reason 申报降级理由` + `(格式:${SKIP_REASON_FORMAT})。`);
|
|
36733
|
+
` + `请按已加载质量门类 skill 的必做清单逐项执行并逐项申报结果(completed=true);` + `确实无法执行的必做项须以结构化 skip_reason 申报降级理由` + `(格式:${SKIP_REASON_FORMAT})。` + `低成本必做项必须实跑后申报;核验申报仅限 workflow 指令白名单限定的高成本必做项。`);
|
|
36379
36734
|
}
|
|
36380
36735
|
}
|
|
36381
36736
|
if (params.verified_tasks?.length || params.failed_tasks?.length) {
|
|
@@ -36581,6 +36936,18 @@ async function agentSubmitExecute(params, ctx) {
|
|
|
36581
36936
|
exemptIds: params.exempt_issue_ids,
|
|
36582
36937
|
newChildren: accepted
|
|
36583
36938
|
});
|
|
36939
|
+
const autoCommitLines = [];
|
|
36940
|
+
if (isReviewerFamily(ctx.agent)) {
|
|
36941
|
+
const ac = await autoCommitWorktreeChanges(wtPath, ctx.agent, params.step_id);
|
|
36942
|
+
if (ac.status === "committed") {
|
|
36943
|
+
autoCommitLines.push(`- ✅ worktree 直改修正已自动提交(${ac.files.length} 个文件,commit message: \`docs(opx): direct fixes by ${ctx.agent} (${params.step_id})\`)`);
|
|
36944
|
+
} else if (ac.status === "failed") {
|
|
36945
|
+
autoCommitLines.push(`- ⚠️ worktree 直改修正自动提交失败:${ac.stderr || "未知错误"}。请编排者安排补提交(worktree 内 git add -u 后 commit)`);
|
|
36946
|
+
}
|
|
36947
|
+
if (ac.untrackedFiles.length > 0) {
|
|
36948
|
+
autoCommitLines.push(`- ⚠️ 存在未跟踪新建文件未纳入自动提交(须纳入版本控制时由编排者/开发者处理):${ac.untrackedFiles.join("、")}`);
|
|
36949
|
+
}
|
|
36950
|
+
}
|
|
36584
36951
|
if (stepPhase === "todo" && params.step_id === "analyze" && params.verdict === "passed" && wtPath && typeof item.metadata["branch_name"] === "string") {
|
|
36585
36952
|
const baseRef = typeof item.metadata["base_ref"] === "string" ? item.metadata["base_ref"] : null;
|
|
36586
36953
|
await reconcileMainPollution(ctx.worktree, wtPath, {
|
|
@@ -36588,7 +36955,7 @@ async function agentSubmitExecute(params, ctx) {
|
|
|
36588
36955
|
baseRef
|
|
36589
36956
|
});
|
|
36590
36957
|
}
|
|
36591
|
-
if (params.step_id === "verify_tool" && agentToReviewLayer(ctx.agent) === "tool") {
|
|
36958
|
+
if (params.step_id === "verify_tool" && agentToReviewLayer(ctx.agent) === "tool" || params.step_id === "quality_review" && ctx.agent === "openspec-reviewer") {
|
|
36592
36959
|
const head = await getCurrentHead(wtPath);
|
|
36593
36960
|
if (head)
|
|
36594
36961
|
item.metadata["_tool_review_checkpoint"] = head;
|
|
@@ -36597,7 +36964,17 @@ async function agentSubmitExecute(params, ctx) {
|
|
|
36597
36964
|
await writeDismissedExemption(ctx.worktree, child, { changeId: state.changeId, exemptedBy: ctx.agent });
|
|
36598
36965
|
}
|
|
36599
36966
|
await writeState(ctx.worktree, state);
|
|
36600
|
-
|
|
36967
|
+
if (autoCommitLines.length === 0)
|
|
36968
|
+
return SUBMIT_OK_MESSAGE;
|
|
36969
|
+
return [
|
|
36970
|
+
`## ✅ ${SUBMIT_OK_MESSAGE}`,
|
|
36971
|
+
"",
|
|
36972
|
+
"### worktree 自动提交",
|
|
36973
|
+
"",
|
|
36974
|
+
...autoCommitLines,
|
|
36975
|
+
""
|
|
36976
|
+
].join(`
|
|
36977
|
+
`);
|
|
36601
36978
|
} finally {
|
|
36602
36979
|
releaseLock(lockPath);
|
|
36603
36980
|
}
|
|
@@ -36985,7 +37362,10 @@ var agentSubmitSchema = {
|
|
|
36985
37362
|
description: "implement step:已完成的 task id(覆盖门禁:全部 open/rejected task 必须被覆盖)",
|
|
36986
37363
|
items: { type: "string" }
|
|
36987
37364
|
},
|
|
36988
|
-
test_results: {
|
|
37365
|
+
test_results: {
|
|
37366
|
+
type: "string",
|
|
37367
|
+
description: "implement / verify_tool step:测试运行结果摘要(implement 为接口测试执行结果——附执行顺序与覆盖接口清单;verify_tool 为 UT 运行结果摘要);quality_review(simple 合并审查)下由开发者在 implement 申报,审查者提交时不生效"
|
|
37368
|
+
},
|
|
36989
37369
|
validation_steps: {
|
|
36990
37370
|
type: "array",
|
|
36991
37371
|
description: "review step:验证步骤执行摘要",
|
|
@@ -37127,7 +37507,7 @@ async function ensureDefaultUnattended(args, ctx) {
|
|
|
37127
37507
|
}
|
|
37128
37508
|
} catch {}
|
|
37129
37509
|
}
|
|
37130
|
-
var PKG_VERSION = "0.
|
|
37510
|
+
var PKG_VERSION = "0.130.0";
|
|
37131
37511
|
function buildMcpServer(worktree, opts = {}) {
|
|
37132
37512
|
const mcp = new McpServer({ name: "openspec-agents", version: PKG_VERSION });
|
|
37133
37513
|
for (const [name, spec] of Object.entries(TOOL_SPECS)) {
|