voidmachine 7.0.1 → 7.0.2
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/core-assets/.claude-plugin/plugin.json +2 -2
- package/core-assets/codex/hooks.json +1 -1
- package/core-assets/data/catalog.v3.json +6 -6
- package/core-assets/data/certification.json +1 -1
- package/core-assets/data/model.json +5 -5
- package/core-assets/hooks/_void-hook.mjs +366 -107
- package/core-assets/skills/void-autopilot/SKILL.md +4 -1
- package/core-assets/skills/void-merge/SKILL.md +22 -15
- package/core-assets/skills/void-verify/references/ci-feedback.md +45 -6
- package/dist/main.js +735 -599
- package/package.json +2 -2
package/dist/main.js
CHANGED
|
@@ -7395,62 +7395,6 @@ var require_dist = __commonJS({
|
|
|
7395
7395
|
}
|
|
7396
7396
|
});
|
|
7397
7397
|
|
|
7398
|
-
// ../../node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js
|
|
7399
|
-
var require_src = __commonJS({
|
|
7400
|
-
"../../node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js"(exports, module) {
|
|
7401
|
-
init_esm_shims();
|
|
7402
|
-
var ESC2 = "\x1B";
|
|
7403
|
-
var CSI2 = `${ESC2}[`;
|
|
7404
|
-
var beep = "\x07";
|
|
7405
|
-
var cursor = {
|
|
7406
|
-
to(x3, y) {
|
|
7407
|
-
if (!y) return `${CSI2}${x3 + 1}G`;
|
|
7408
|
-
return `${CSI2}${y + 1};${x3 + 1}H`;
|
|
7409
|
-
},
|
|
7410
|
-
move(x3, y) {
|
|
7411
|
-
let ret = "";
|
|
7412
|
-
if (x3 < 0) ret += `${CSI2}${-x3}D`;
|
|
7413
|
-
else if (x3 > 0) ret += `${CSI2}${x3}C`;
|
|
7414
|
-
if (y < 0) ret += `${CSI2}${-y}A`;
|
|
7415
|
-
else if (y > 0) ret += `${CSI2}${y}B`;
|
|
7416
|
-
return ret;
|
|
7417
|
-
},
|
|
7418
|
-
up: (count = 1) => `${CSI2}${count}A`,
|
|
7419
|
-
down: (count = 1) => `${CSI2}${count}B`,
|
|
7420
|
-
forward: (count = 1) => `${CSI2}${count}C`,
|
|
7421
|
-
backward: (count = 1) => `${CSI2}${count}D`,
|
|
7422
|
-
nextLine: (count = 1) => `${CSI2}E`.repeat(count),
|
|
7423
|
-
prevLine: (count = 1) => `${CSI2}F`.repeat(count),
|
|
7424
|
-
left: `${CSI2}G`,
|
|
7425
|
-
hide: `${CSI2}?25l`,
|
|
7426
|
-
show: `${CSI2}?25h`,
|
|
7427
|
-
save: `${ESC2}7`,
|
|
7428
|
-
restore: `${ESC2}8`
|
|
7429
|
-
};
|
|
7430
|
-
var scroll = {
|
|
7431
|
-
up: (count = 1) => `${CSI2}S`.repeat(count),
|
|
7432
|
-
down: (count = 1) => `${CSI2}T`.repeat(count)
|
|
7433
|
-
};
|
|
7434
|
-
var erase = {
|
|
7435
|
-
screen: `${CSI2}2J`,
|
|
7436
|
-
up: (count = 1) => `${CSI2}1J`.repeat(count),
|
|
7437
|
-
down: (count = 1) => `${CSI2}J`.repeat(count),
|
|
7438
|
-
line: `${CSI2}2K`,
|
|
7439
|
-
lineEnd: `${CSI2}K`,
|
|
7440
|
-
lineStart: `${CSI2}1K`,
|
|
7441
|
-
lines(count) {
|
|
7442
|
-
let clear = "";
|
|
7443
|
-
for (let i = 0; i < count; i++)
|
|
7444
|
-
clear += this.line + (i < count - 1 ? cursor.up() : "");
|
|
7445
|
-
if (count)
|
|
7446
|
-
clear += cursor.left;
|
|
7447
|
-
return clear;
|
|
7448
|
-
}
|
|
7449
|
-
};
|
|
7450
|
-
module.exports = { cursor, scroll, erase, beep };
|
|
7451
|
-
}
|
|
7452
|
-
});
|
|
7453
|
-
|
|
7454
7398
|
// ../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/constants.js
|
|
7455
7399
|
var require_constants = __commonJS({
|
|
7456
7400
|
"../../node_modules/.pnpm/picomatch@4.0.5/node_modules/picomatch/lib/constants.js"(exports, module) {
|
|
@@ -9218,6 +9162,62 @@ var require_picomatch2 = __commonJS({
|
|
|
9218
9162
|
}
|
|
9219
9163
|
});
|
|
9220
9164
|
|
|
9165
|
+
// ../../node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js
|
|
9166
|
+
var require_src = __commonJS({
|
|
9167
|
+
"../../node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js"(exports, module) {
|
|
9168
|
+
init_esm_shims();
|
|
9169
|
+
var ESC2 = "\x1B";
|
|
9170
|
+
var CSI2 = `${ESC2}[`;
|
|
9171
|
+
var beep = "\x07";
|
|
9172
|
+
var cursor = {
|
|
9173
|
+
to(x3, y) {
|
|
9174
|
+
if (!y) return `${CSI2}${x3 + 1}G`;
|
|
9175
|
+
return `${CSI2}${y + 1};${x3 + 1}H`;
|
|
9176
|
+
},
|
|
9177
|
+
move(x3, y) {
|
|
9178
|
+
let ret = "";
|
|
9179
|
+
if (x3 < 0) ret += `${CSI2}${-x3}D`;
|
|
9180
|
+
else if (x3 > 0) ret += `${CSI2}${x3}C`;
|
|
9181
|
+
if (y < 0) ret += `${CSI2}${-y}A`;
|
|
9182
|
+
else if (y > 0) ret += `${CSI2}${y}B`;
|
|
9183
|
+
return ret;
|
|
9184
|
+
},
|
|
9185
|
+
up: (count = 1) => `${CSI2}${count}A`,
|
|
9186
|
+
down: (count = 1) => `${CSI2}${count}B`,
|
|
9187
|
+
forward: (count = 1) => `${CSI2}${count}C`,
|
|
9188
|
+
backward: (count = 1) => `${CSI2}${count}D`,
|
|
9189
|
+
nextLine: (count = 1) => `${CSI2}E`.repeat(count),
|
|
9190
|
+
prevLine: (count = 1) => `${CSI2}F`.repeat(count),
|
|
9191
|
+
left: `${CSI2}G`,
|
|
9192
|
+
hide: `${CSI2}?25l`,
|
|
9193
|
+
show: `${CSI2}?25h`,
|
|
9194
|
+
save: `${ESC2}7`,
|
|
9195
|
+
restore: `${ESC2}8`
|
|
9196
|
+
};
|
|
9197
|
+
var scroll = {
|
|
9198
|
+
up: (count = 1) => `${CSI2}S`.repeat(count),
|
|
9199
|
+
down: (count = 1) => `${CSI2}T`.repeat(count)
|
|
9200
|
+
};
|
|
9201
|
+
var erase = {
|
|
9202
|
+
screen: `${CSI2}2J`,
|
|
9203
|
+
up: (count = 1) => `${CSI2}1J`.repeat(count),
|
|
9204
|
+
down: (count = 1) => `${CSI2}J`.repeat(count),
|
|
9205
|
+
line: `${CSI2}2K`,
|
|
9206
|
+
lineEnd: `${CSI2}K`,
|
|
9207
|
+
lineStart: `${CSI2}1K`,
|
|
9208
|
+
lines(count) {
|
|
9209
|
+
let clear = "";
|
|
9210
|
+
for (let i = 0; i < count; i++)
|
|
9211
|
+
clear += this.line + (i < count - 1 ? cursor.up() : "");
|
|
9212
|
+
if (count)
|
|
9213
|
+
clear += cursor.left;
|
|
9214
|
+
return clear;
|
|
9215
|
+
}
|
|
9216
|
+
};
|
|
9217
|
+
module.exports = { cursor, scroll, erase, beep };
|
|
9218
|
+
}
|
|
9219
|
+
});
|
|
9220
|
+
|
|
9221
9221
|
// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/constants.js
|
|
9222
9222
|
var require_constants2 = __commonJS({
|
|
9223
9223
|
"../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/constants.js"(exports, module) {
|
|
@@ -17955,7 +17955,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
17955
17955
|
var NONE = 0;
|
|
17956
17956
|
var ASSUMED = 1;
|
|
17957
17957
|
var PROVEN = 2;
|
|
17958
|
-
function isRecursive(inst, stack,
|
|
17958
|
+
function isRecursive(inst, stack, resolve45) {
|
|
17959
17959
|
const cached2 = recursive.get(inst);
|
|
17960
17960
|
if (cached2 !== void 0)
|
|
17961
17961
|
return cached2 ? PROVEN : NONE;
|
|
@@ -17965,7 +17965,7 @@ function isRecursive(inst, stack, resolve43) {
|
|
|
17965
17965
|
let result = NONE;
|
|
17966
17966
|
const check3 = (child) => {
|
|
17967
17967
|
if (result !== PROVEN && child?._zod) {
|
|
17968
|
-
const answer2 = isRecursive(child, stack,
|
|
17968
|
+
const answer2 = isRecursive(child, stack, resolve45);
|
|
17969
17969
|
if (answer2 > result)
|
|
17970
17970
|
result = answer2;
|
|
17971
17971
|
}
|
|
@@ -17976,7 +17976,7 @@ function isRecursive(inst, stack, resolve43) {
|
|
|
17976
17976
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
17977
17977
|
if (!desc.enumerable)
|
|
17978
17978
|
continue;
|
|
17979
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
17979
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve45) : NONE;
|
|
17980
17980
|
if (child > answer2)
|
|
17981
17981
|
answer2 = child;
|
|
17982
17982
|
}
|
|
@@ -18040,7 +18040,7 @@ function isRecursive(inst, stack, resolve43) {
|
|
|
18040
18040
|
break;
|
|
18041
18041
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
18042
18042
|
case "lazy": {
|
|
18043
|
-
const inner = def._cachedInner ?? (
|
|
18043
|
+
const inner = def._cachedInner ?? (resolve45 ? inst._zod.innerType : void 0);
|
|
18044
18044
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
18045
18045
|
break;
|
|
18046
18046
|
}
|
|
@@ -33518,6 +33518,12 @@ init_esm_shims();
|
|
|
33518
33518
|
// ../hook-runner/src/enforcement/shell-writes.ts
|
|
33519
33519
|
init_esm_shims();
|
|
33520
33520
|
|
|
33521
|
+
// ../hook-runner/src/enforcement/shell-reads.ts
|
|
33522
|
+
init_esm_shims();
|
|
33523
|
+
|
|
33524
|
+
// ../hook-runner/src/enforcement/secret-read.ts
|
|
33525
|
+
init_esm_shims();
|
|
33526
|
+
|
|
33521
33527
|
// ../hook-runner/src/enforcement/original-source.ts
|
|
33522
33528
|
init_esm_shims();
|
|
33523
33529
|
|
|
@@ -33564,6 +33570,14 @@ function discoverProjectRoot(start) {
|
|
|
33564
33570
|
current2 = parent;
|
|
33565
33571
|
}
|
|
33566
33572
|
}
|
|
33573
|
+
var DEFAULT_PROJECT_PATHS = {
|
|
33574
|
+
business: ["src/**", "apps/*/src/**"],
|
|
33575
|
+
tests: ["src/**/*.test.{ts,tsx}", "apps/*/src/**/*.test.{ts,tsx}"],
|
|
33576
|
+
spikes: ["scripts/spike-*", "apps/*/scripts/spike-*"],
|
|
33577
|
+
serverActions: ["src/app/(api|actions)/**", "apps/*/src/app/(api|actions)/**"],
|
|
33578
|
+
contracts: ["src/lib/contracts/**", "apps/*/src/lib/contracts/**"],
|
|
33579
|
+
e2e: ["tests/e2e/**", "apps/*/tests/e2e/**"]
|
|
33580
|
+
};
|
|
33567
33581
|
|
|
33568
33582
|
// ../hook-runner/src/project-roots.ts
|
|
33569
33583
|
var GIT_TIMEOUT_MS = 5e3;
|
|
@@ -36142,6 +36156,9 @@ function authorizedTargetedRequest(events, request, history) {
|
|
|
36142
36156
|
const recoveredBlockers = writerBindingCorrectionFindings(events);
|
|
36143
36157
|
return recovery !== void 0 && correction.seq > recovery.seq && count === 1 && reviewField(writer, "writerId") === original.writerId && binding3 !== void 0 && typeof binding3 === "object" && binding3 !== null && "completionEventId" in binding3 && binding3.completionEventId === previous.event.eventId && history.length === 1 && recoveredBlockers.length > 0 && sameMembers(recoveredBlockers.map((finding) => finding.findingId), knownBlockers.map((finding) => finding.findingId)) && events.filter((event) => event.kind === "lead-writer.requested" && reviewField(event, "actionKind") === "run-correction").length === 1 && events.filter((event) => event.kind === "specialist.requested" && event.subject === request.subject && event.seq > recovery.seq && event.seq <= request.seq).length === 1;
|
|
36144
36158
|
}
|
|
36159
|
+
function hasBlockingReview(completion) {
|
|
36160
|
+
return completion.review !== void 0 && completion.findings.some((finding) => finding.classification === "blocking") && completion.findings.every((finding) => finding.classification !== void 0);
|
|
36161
|
+
}
|
|
36145
36162
|
function canContinueNativeReview(events, request, contextId) {
|
|
36146
36163
|
const start = events[0];
|
|
36147
36164
|
if (!start || start.kind !== "mission.started" || reviewField(request, "planHash") !== reviewField(start, "planHash") || reviewField(request, "runtime") !== reviewField(start, "runtime") || request.kind !== "specialist.requested" || request.source !== "void-harness:mission.dispatch" || request.subject !== "core:independent-code-reviewer" || reviewField(request, "stage") !== "post-implementation" || !validNativeContextId(contextId) || events.some((event) => event.missionId !== request.missionId))
|
|
@@ -36152,7 +36169,7 @@ function canContinueNativeReview(events, request, contextId) {
|
|
|
36152
36169
|
const prior = history.filter((item) => item !== void 0);
|
|
36153
36170
|
const first = prior[0];
|
|
36154
36171
|
const amendment = writerBindingRecovery(events);
|
|
36155
|
-
if (!first || first.completion.review?.scope.kind !== "general" ||
|
|
36172
|
+
if (!first || first.completion.review?.scope.kind !== "general" || !hasBlockingReview(first.completion) || amendment !== void 0 && prior.length !== 1 || new Set(prior.map((item) => item.completion.completionId)).size !== prior.length || events.some((event) => event.seq < request.seq && ["specialist.started", "specialist.completed"].includes(event.kind) && reviewField(event, "contextId") === contextId && (event.subject !== request.subject || reviewField(event, "stage") !== "post-implementation")) || events.filter((event) => event.kind === "specialist.completed" && event.subject === request.subject && reviewField(event, "stage") === "post-implementation" && event.seq < request.seq).at(-1)?.eventId !== prior.at(-1)?.event.eventId)
|
|
36156
36173
|
return false;
|
|
36157
36174
|
for (const [index, item] of prior.entries()) {
|
|
36158
36175
|
const bound = boundNativeRequest(events, item);
|
|
@@ -36415,7 +36432,7 @@ function mergeFindings(completions2) {
|
|
|
36415
36432
|
function decideStatus(input2) {
|
|
36416
36433
|
if (input2.issues.length > 0)
|
|
36417
36434
|
return "degraded";
|
|
36418
|
-
if (input2.current.some((item) => item.completion.verdict === "degraded")) {
|
|
36435
|
+
if (input2.current.some((item) => item.completion.verdict === "degraded" && (input2.correctionBatches === void 0 || !hasBlockingReview(item.completion) || !input2.findings.some((finding) => finding.classification === "blocking")))) {
|
|
36419
36436
|
return "degraded";
|
|
36420
36437
|
}
|
|
36421
36438
|
if (input2.stale.length > 0) {
|
|
@@ -37266,17 +37283,17 @@ function admitStoppedMission(input2, projectedHistory = input2.stream.events) {
|
|
|
37266
37283
|
const migration = validatedSpecialistContractMigrationBoundary(events);
|
|
37267
37284
|
if (!migration.ok)
|
|
37268
37285
|
return refuse3("invalid-migration-receipt", migration.reasons.join("; "));
|
|
37269
|
-
const
|
|
37270
|
-
if (
|
|
37286
|
+
const boundary2 = observation3.stage === "post-implementation" ? migration.migration : void 0;
|
|
37287
|
+
if (boundary2 !== void 0 && observation3.contractVersions[boundary2.receipt.specialistId] !== boundary2.receipt.toVersion) {
|
|
37271
37288
|
return refuse3("inconsistent-review", "Recovery must observe the authenticated effective specialist contract");
|
|
37272
37289
|
}
|
|
37273
37290
|
const reviewInput = {
|
|
37274
37291
|
stage: observation3.stage,
|
|
37275
37292
|
expectedSource: observation3.expectedSource,
|
|
37276
|
-
...
|
|
37277
|
-
specialistId:
|
|
37278
|
-
afterSeq:
|
|
37279
|
-
reviewRound:
|
|
37293
|
+
...boundary2 === void 0 ? {} : { contractMigration: {
|
|
37294
|
+
specialistId: boundary2.receipt.specialistId,
|
|
37295
|
+
afterSeq: boundary2.seq,
|
|
37296
|
+
reviewRound: boundary2.receipt.reviewRound
|
|
37280
37297
|
} },
|
|
37281
37298
|
...stageStart === void 0 ? {} : { stageStartSeqExclusive: stageStart },
|
|
37282
37299
|
...lastWriter === void 0 ? {} : { afterSeqExclusive: lastWriter },
|
|
@@ -39210,13 +39227,16 @@ function decideReviewPhase(start, review, baseVerdict, stage) {
|
|
|
39210
39227
|
}
|
|
39211
39228
|
function boundedReceiptReasons(input2, start, events) {
|
|
39212
39229
|
const lastWriter = writerCompletions(input2).at(-1)?.seq ?? 0;
|
|
39230
|
+
const recovery = writerBindingRecovery(events);
|
|
39231
|
+
const binding3 = recovery && record15(lifecycleField(recovery, "writerBinding"));
|
|
39213
39232
|
return events.filter((event) => event.kind === "specialist.completed" && event.seq > lastWriter && event.subject === "core:independent-code-reviewer" && lifecycleField(event, "stage") === "post-implementation").flatMap((event) => {
|
|
39214
39233
|
const result = parseSpecialistCompletionValue(lifecycleField(event, "completion"));
|
|
39215
39234
|
const receipt2 = result?.review;
|
|
39216
39235
|
if (result === void 0 || receipt2 === void 0 || input2.reviewSubject === void 0) {
|
|
39217
39236
|
return ["Independent review requires its durable committed subject and reviewer receipt"];
|
|
39218
39237
|
}
|
|
39219
|
-
|
|
39238
|
+
const subject = binding3?.["completionEventId"] === event.eventId ? lifecycleField(event, "reviewSubject") : input2.reviewSubject;
|
|
39239
|
+
if (!isReviewSubject(subject) || !sameReviewSubject(receipt2, subject) || receipt2.taskId !== event.missionId || receipt2.writerId !== start.leadWriterId || receipt2.reviewerId === start.leadWriterId) {
|
|
39220
39240
|
return ["Independent review receipt does not match the observed task, commit, base, or writer"];
|
|
39221
39241
|
}
|
|
39222
39242
|
if (receipt2.provenance.kind === "native-context" && receipt2.provenance.contextId !== lifecycleField(event, "contextId")) {
|
|
@@ -39225,7 +39245,7 @@ function boundedReceiptReasons(input2, start, events) {
|
|
|
39225
39245
|
if (result.findings.some((finding) => finding.classification === void 0)) {
|
|
39226
39246
|
return ["Bounded findings require an explicit consequence classification"];
|
|
39227
39247
|
}
|
|
39228
|
-
return [];
|
|
39248
|
+
return unboundCompletionReasons(input2, start.runtime, [event]);
|
|
39229
39249
|
});
|
|
39230
39250
|
}
|
|
39231
39251
|
function recoveredPreparationTargets(events) {
|
|
@@ -39247,11 +39267,11 @@ function recoveredPreparationTargets(events) {
|
|
|
39247
39267
|
specialistIds: events.filter((item) => item.kind === "specialist.completed" && ids.includes(item.eventId)).map((item) => item.subject)
|
|
39248
39268
|
};
|
|
39249
39269
|
}
|
|
39250
|
-
function retainedPreparationSpecialists(input2, events,
|
|
39270
|
+
function retainedPreparationSpecialists(input2, events, boundary2, targets) {
|
|
39251
39271
|
return requiredSpecialists(input2.plan, "pre-implementation").filter((id4) => {
|
|
39252
39272
|
if (targets.includes(id4))
|
|
39253
39273
|
return false;
|
|
39254
|
-
const latest = events.filter((item) => item.kind === "specialist.completed" && item.subject === id4 && item.seq <
|
|
39274
|
+
const latest = events.filter((item) => item.kind === "specialist.completed" && item.subject === id4 && item.seq < boundary2 && lifecycleField(item, "stage") === "pre-implementation").at(-1);
|
|
39255
39275
|
if (latest === void 0)
|
|
39256
39276
|
return false;
|
|
39257
39277
|
const result = record15(lifecycleField(latest, "completion") ?? null);
|
|
@@ -39444,7 +39464,7 @@ function orchestrateMissionTeam(originalInput) {
|
|
|
39444
39464
|
}, input2.specialistRuntime);
|
|
39445
39465
|
}
|
|
39446
39466
|
}
|
|
39447
|
-
|
|
39467
|
+
let postReview = firstImplementationSeq === void 0 || lastWriterSeq === void 0 ? void 0 : reduceReviewLoop({
|
|
39448
39468
|
stage: "post-implementation",
|
|
39449
39469
|
expectedSource,
|
|
39450
39470
|
stageStartSeqExclusive: firstImplementationSeq,
|
|
@@ -39470,27 +39490,26 @@ function orchestrateMissionTeam(originalInput) {
|
|
|
39470
39490
|
if (canonicalJsonHash(subject) !== canonicalJsonHash(input2.reviewSubject) || canonicalJsonHash(observation3?.["currentInputHashes"]) !== canonicalJsonHash(Object.fromEntries(Object.keys(record15(observation3?.["currentInputHashes"] ?? null) ?? {}).map((id4) => [id4, input2.currentInputHashesByStage["post-implementation"][id4]])))) {
|
|
39471
39491
|
return stopped("blocked", postReview, baseVerdict, ["Writer binding recovery observations changed before correction"]);
|
|
39472
39492
|
}
|
|
39473
|
-
|
|
39474
|
-
|
|
39475
|
-
|
|
39476
|
-
|
|
39477
|
-
|
|
39478
|
-
|
|
39479
|
-
findingIds: writerBindingCorrectionFindings(reviewEvents).map((finding) => finding.findingId)
|
|
39480
|
-
},
|
|
39481
|
-
review: postReview,
|
|
39482
|
-
verdict: overrideVerdict(baseVerdict, "blocked", reasons),
|
|
39483
|
-
reasons
|
|
39484
|
-
}, input2.specialistRuntime);
|
|
39493
|
+
postReview = {
|
|
39494
|
+
...postReview,
|
|
39495
|
+
status: "correction-required",
|
|
39496
|
+
readyForVerdict: false,
|
|
39497
|
+
findings: writerBindingCorrectionFindings(reviewEvents)
|
|
39498
|
+
};
|
|
39485
39499
|
}
|
|
39486
39500
|
if (bindingRecovery && postReview && input2.stream.events.some((event) => event.seq > bindingRecovery.seq && event.kind === "specialist.completed") && !postReview.readyForVerdict) {
|
|
39487
39501
|
return stopped("blocked", postReview, baseVerdict, ["The single targeted continuation is spent; retain the original review budget"]);
|
|
39488
39502
|
}
|
|
39503
|
+
if (start.boundedReview && postReview) {
|
|
39504
|
+
const receiptReasons = boundedReceiptReasons(input2, start, reviewEvents);
|
|
39505
|
+
if (receiptReasons.length > 0)
|
|
39506
|
+
return stopped("degraded", postReview, baseVerdict, receiptReasons);
|
|
39507
|
+
}
|
|
39489
39508
|
if (postReview?.status === "blocked" || postReview?.status === "degraded") {
|
|
39490
39509
|
return applyRuntimeCertification(decideReviewPhase(start, postReview, baseVerdict, "post-implementation"), input2.specialistRuntime);
|
|
39491
39510
|
}
|
|
39492
39511
|
const correctiveFindingIds = pendingRecoveredCorrectionFindingIds(input2.stream.events);
|
|
39493
|
-
const correctiveContinuation = pendingEvidence !== void 0 && obligations.issues.length === 0 && firstImplementationSeq !== void 0 && correctiveFindingIds.length > 0;
|
|
39512
|
+
const correctiveContinuation = pendingEvidence !== void 0 && obligations.issues.length === 0 && firstImplementationSeq !== void 0 && (correctiveFindingIds.length > 0 || postReview?.status === "correction-required" && postReview.findings.some((finding) => finding.classification === "blocking"));
|
|
39494
39513
|
if (pendingEvidence !== void 0 && !correctiveContinuation) {
|
|
39495
39514
|
return applyRuntimeCertification(pendingEvidence, input2.specialistRuntime);
|
|
39496
39515
|
}
|
|
@@ -39548,11 +39567,6 @@ function orchestrateMissionTeam(originalInput) {
|
|
|
39548
39567
|
if (firstWriterSeq === void 0 || firstImplementationSeq === void 0 || lastWriterSeq === void 0 || postReview === void 0) {
|
|
39549
39568
|
throw new Error("MISSION_TEAM_INVARIANT: writer completion boundary is missing");
|
|
39550
39569
|
}
|
|
39551
|
-
if (start.boundedReview && postReview.missingSpecialists.length === 0) {
|
|
39552
|
-
const receiptReasons = boundedReceiptReasons(input2, start, reviewEvents);
|
|
39553
|
-
if (receiptReasons.length > 0)
|
|
39554
|
-
return stopped("degraded", postReview, baseVerdict, receiptReasons);
|
|
39555
|
-
}
|
|
39556
39570
|
if (postReview.readyForVerdict) {
|
|
39557
39571
|
const completionEvidence = obligationStop(evidenceObligations(input2, expectedSource, "completion"), postReview, baseVerdict);
|
|
39558
39572
|
if (completionEvidence !== void 0) {
|
|
@@ -41355,13 +41369,13 @@ function estimateTokens2(text8) {
|
|
|
41355
41369
|
}
|
|
41356
41370
|
var MAX_SOURCE_BYTES2 = 1024 * 1024;
|
|
41357
41371
|
var MAX_DIRECTORY_ENTRIES = 1e4;
|
|
41358
|
-
function within2(
|
|
41359
|
-
const path3 = relative(
|
|
41372
|
+
function within2(boundary2, target) {
|
|
41373
|
+
const path3 = relative(boundary2, target);
|
|
41360
41374
|
return path3 === "" || !path3.startsWith("..") && !isAbsolute(path3);
|
|
41361
41375
|
}
|
|
41362
|
-
function sourceNames(
|
|
41376
|
+
function sourceNames(boundary2, directory) {
|
|
41363
41377
|
if (!existsSync(directory)) return [];
|
|
41364
|
-
const canonicalBoundary = realpathSync(
|
|
41378
|
+
const canonicalBoundary = realpathSync(boundary2);
|
|
41365
41379
|
const metadata2 = lstatSync(directory);
|
|
41366
41380
|
if (metadata2.isSymbolicLink()) {
|
|
41367
41381
|
throw new Error(`GRAPH_SOURCE_PATH_ESCAPE: directory is a symlink: ${directory}`);
|
|
@@ -41376,13 +41390,13 @@ function sourceNames(boundary, directory) {
|
|
|
41376
41390
|
}
|
|
41377
41391
|
return names;
|
|
41378
41392
|
}
|
|
41379
|
-
function sourceText(
|
|
41393
|
+
function sourceText(boundary2, path3) {
|
|
41380
41394
|
if (!existsSync(path3)) return void 0;
|
|
41381
41395
|
const metadata2 = lstatSync(path3);
|
|
41382
41396
|
if (metadata2.isSymbolicLink()) {
|
|
41383
41397
|
throw new Error(`GRAPH_SOURCE_PATH_ESCAPE: source is a symlink: ${path3}`);
|
|
41384
41398
|
}
|
|
41385
|
-
const canonicalBoundary = realpathSync(
|
|
41399
|
+
const canonicalBoundary = realpathSync(boundary2);
|
|
41386
41400
|
const canonicalPath = realpathSync(path3);
|
|
41387
41401
|
if (!metadata2.isFile() || !within2(canonicalBoundary, canonicalPath)) {
|
|
41388
41402
|
throw new Error(`GRAPH_SOURCE_PATH_ESCAPE: source leaves its declared root: ${path3}`);
|
|
@@ -41490,14 +41504,14 @@ function scanSourceTree(coreDir, packsDir) {
|
|
|
41490
41504
|
}
|
|
41491
41505
|
return { skills, agents: agents2, hooks, commands, packs, profiles, workflowDefs };
|
|
41492
41506
|
}
|
|
41493
|
-
function readMdDir(
|
|
41494
|
-
return readDir(
|
|
41507
|
+
function readMdDir(boundary2, dir, rel) {
|
|
41508
|
+
return readDir(boundary2, dir, ".md", rel);
|
|
41495
41509
|
}
|
|
41496
|
-
function readDir(
|
|
41510
|
+
function readDir(boundary2, dir, ext, rel) {
|
|
41497
41511
|
if (!existsSync(dir)) return [];
|
|
41498
|
-
return sourceNames(
|
|
41512
|
+
return sourceNames(boundary2, dir).filter((f2) => f2.endsWith(ext)).flatMap((f2) => {
|
|
41499
41513
|
const full = join(dir, f2);
|
|
41500
|
-
const text8 = sourceText(
|
|
41514
|
+
const text8 = sourceText(boundary2, full);
|
|
41501
41515
|
return text8 === void 0 ? [] : [{ name: f2.slice(0, -ext.length), source: rel(full), text: text8 }];
|
|
41502
41516
|
});
|
|
41503
41517
|
}
|
|
@@ -44011,6 +44025,432 @@ function observeKeptTracked(projectRoot2) {
|
|
|
44011
44025
|
});
|
|
44012
44026
|
}
|
|
44013
44027
|
|
|
44028
|
+
// src/lib/lint-exclusion.ts
|
|
44029
|
+
init_esm_shims();
|
|
44030
|
+
var import_picomatch = __toESM(require_picomatch2());
|
|
44031
|
+
|
|
44032
|
+
// src/lib/void-migration.ts
|
|
44033
|
+
init_esm_shims();
|
|
44034
|
+
var EMPTY = Object.freeze({
|
|
44035
|
+
moved: [],
|
|
44036
|
+
conflicts: [],
|
|
44037
|
+
parked: [],
|
|
44038
|
+
gitignoreBlockRemoved: false
|
|
44039
|
+
});
|
|
44040
|
+
async function freeParkedName(target) {
|
|
44041
|
+
if (!existsSync(`${target}.legacy`)) return `${target}.legacy`;
|
|
44042
|
+
for (let attempt = 2; attempt < 100; attempt += 1) {
|
|
44043
|
+
const candidate = `${target}.legacy.${String(attempt)}`;
|
|
44044
|
+
if (!existsSync(candidate)) return candidate;
|
|
44045
|
+
}
|
|
44046
|
+
return `${target}.legacy.overflow`;
|
|
44047
|
+
}
|
|
44048
|
+
async function mergeInto(source2, destination) {
|
|
44049
|
+
const info = await stat(source2);
|
|
44050
|
+
if (!info.isDirectory()) {
|
|
44051
|
+
if (!existsSync(destination)) {
|
|
44052
|
+
await mkdir(join(destination, ".."), { recursive: true });
|
|
44053
|
+
await rename(source2, destination);
|
|
44054
|
+
return false;
|
|
44055
|
+
}
|
|
44056
|
+
await rename(source2, await freeParkedName(destination));
|
|
44057
|
+
return true;
|
|
44058
|
+
}
|
|
44059
|
+
await mkdir(destination, { recursive: true });
|
|
44060
|
+
let parked = false;
|
|
44061
|
+
for (const entry of await readdir(source2)) {
|
|
44062
|
+
if (await mergeInto(join(source2, entry), join(destination, entry))) parked = true;
|
|
44063
|
+
}
|
|
44064
|
+
await rm(source2, { recursive: true, force: true });
|
|
44065
|
+
return parked;
|
|
44066
|
+
}
|
|
44067
|
+
function planVoidMigration(root) {
|
|
44068
|
+
const movable = [];
|
|
44069
|
+
const conflicts = [];
|
|
44070
|
+
for (const entry of pendingMigrations(root)) {
|
|
44071
|
+
if (existsSync(voidMachinePath(root, entry))) conflicts.push(entry);
|
|
44072
|
+
else movable.push(entry);
|
|
44073
|
+
}
|
|
44074
|
+
return { movable, conflicts };
|
|
44075
|
+
}
|
|
44076
|
+
async function ownedInstallPaths(root) {
|
|
44077
|
+
const manifestPath = join(root, ...INSTALL_MANIFEST_PATH.split("/"));
|
|
44078
|
+
if (existsSync(manifestPath)) {
|
|
44079
|
+
try {
|
|
44080
|
+
const manifest = parseInstallManifest(await readFile(manifestPath, "utf8"));
|
|
44081
|
+
if (manifest !== void 0) {
|
|
44082
|
+
return new Set(manifest.files.map((file2) => file2.path));
|
|
44083
|
+
}
|
|
44084
|
+
} catch {
|
|
44085
|
+
}
|
|
44086
|
+
}
|
|
44087
|
+
const receipt2 = await readInstallReceipt(root);
|
|
44088
|
+
if (receipt2 === void 0) return void 0;
|
|
44089
|
+
return new Set(receipt2.files.map((file2) => file2.path));
|
|
44090
|
+
}
|
|
44091
|
+
async function ownedDerivedPaths(root) {
|
|
44092
|
+
const paths = await ownedInstallPaths(root);
|
|
44093
|
+
return paths === void 0 ? void 0 : new Set([...paths].filter(isOwnedDerived));
|
|
44094
|
+
}
|
|
44095
|
+
async function untrackDerived(root, dryRun = false) {
|
|
44096
|
+
const owned = await ownedDerivedPaths(root);
|
|
44097
|
+
if (owned === void 0) {
|
|
44098
|
+
return { untracked: [], error: "no readable install manifest or receipt \u2014 nothing here can be proven harness-owned" };
|
|
44099
|
+
}
|
|
44100
|
+
let listed;
|
|
44101
|
+
try {
|
|
44102
|
+
listed = execFileSync("git", ["ls-files", "-z", "--", ".void", ".claude", ".agents", ".codex"], {
|
|
44103
|
+
cwd: root,
|
|
44104
|
+
encoding: "utf8",
|
|
44105
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
44106
|
+
});
|
|
44107
|
+
} catch {
|
|
44108
|
+
return { untracked: [], error: "not a git repository, or git is unavailable" };
|
|
44109
|
+
}
|
|
44110
|
+
const untracked = listed.split("\0").filter((path3) => path3 !== "" && owned.has(path3.split("\\").join("/")));
|
|
44111
|
+
if (untracked.length === 0 || dryRun) return { untracked };
|
|
44112
|
+
try {
|
|
44113
|
+
for (let index = 0; index < untracked.length; index += 200) {
|
|
44114
|
+
execFileSync("git", ["rm", "--cached", "--quiet", "--", ...untracked.slice(index, index + 200)], {
|
|
44115
|
+
cwd: root,
|
|
44116
|
+
stdio: ["ignore", "ignore", "pipe"]
|
|
44117
|
+
});
|
|
44118
|
+
}
|
|
44119
|
+
} catch (error62) {
|
|
44120
|
+
return { untracked: [], error: error62 instanceof Error ? error62.message.split("\n")[0] ?? "git rm failed" : "git rm failed" };
|
|
44121
|
+
}
|
|
44122
|
+
return { untracked };
|
|
44123
|
+
}
|
|
44124
|
+
async function migrateVoidLayout(root, dryRun = false) {
|
|
44125
|
+
if (!existsSync(join(root, ".void"))) return EMPTY;
|
|
44126
|
+
const { movable, conflicts } = planVoidMigration(root);
|
|
44127
|
+
if (!dryRun) writeExcludeBlock(root, [...await ownedDerivedPaths(root) ?? []]);
|
|
44128
|
+
const gitignorePath = join(root, ".gitignore");
|
|
44129
|
+
const original = existsSync(gitignorePath) ? await readFile(gitignorePath, "utf8") : "";
|
|
44130
|
+
const stripped = stripManagedBlock(original);
|
|
44131
|
+
const gitignoreBlockRemoved = stripped !== original;
|
|
44132
|
+
const pending = [...movable, ...conflicts].sort();
|
|
44133
|
+
const failed2 = [];
|
|
44134
|
+
if (dryRun) return { moved: pending, conflicts: [], parked: [], gitignoreBlockRemoved };
|
|
44135
|
+
if (pending.length > 0) {
|
|
44136
|
+
await mkdir(voidMachineDir(root), { recursive: true });
|
|
44137
|
+
await mkdir(voidInstalledDir(root), { recursive: true });
|
|
44138
|
+
}
|
|
44139
|
+
const moved = [];
|
|
44140
|
+
const parked = [];
|
|
44141
|
+
for (const entry of pending) {
|
|
44142
|
+
try {
|
|
44143
|
+
const sources = [legacyVoidPath(root, entry), previousMachinePath(root, entry)].filter((source2) => existsSync(source2));
|
|
44144
|
+
if (ownershipOf(entry) === "derived") {
|
|
44145
|
+
for (const source2 of sources) await rm(source2, { recursive: true, force: true });
|
|
44146
|
+
if (sources.length > 0) moved.push(entry);
|
|
44147
|
+
continue;
|
|
44148
|
+
}
|
|
44149
|
+
let touched = false;
|
|
44150
|
+
for (const source2 of sources) {
|
|
44151
|
+
if (await mergeInto(source2, voidMachinePath(root, migratedName(entry)))) touched = true;
|
|
44152
|
+
}
|
|
44153
|
+
if (touched) parked.push(entry);
|
|
44154
|
+
moved.push(entry);
|
|
44155
|
+
} catch {
|
|
44156
|
+
failed2.push(entry);
|
|
44157
|
+
}
|
|
44158
|
+
}
|
|
44159
|
+
try {
|
|
44160
|
+
const previous = join(root, ".void", "local");
|
|
44161
|
+
if (existsSync(previous)) {
|
|
44162
|
+
for (const entry of await readdir(previous)) {
|
|
44163
|
+
await mergeInto(join(previous, entry), voidMachinePath(root, entry));
|
|
44164
|
+
}
|
|
44165
|
+
}
|
|
44166
|
+
} catch {
|
|
44167
|
+
}
|
|
44168
|
+
try {
|
|
44169
|
+
const previous = join(root, ".void", "local");
|
|
44170
|
+
if (existsSync(previous) && (await readdir(previous)).length === 0) {
|
|
44171
|
+
await rm(previous, { recursive: true, force: true });
|
|
44172
|
+
}
|
|
44173
|
+
} catch {
|
|
44174
|
+
}
|
|
44175
|
+
if (gitignoreBlockRemoved) await writeFile(gitignorePath, stripped);
|
|
44176
|
+
return { moved, conflicts: failed2.sort(), parked: parked.sort(), gitignoreBlockRemoved };
|
|
44177
|
+
}
|
|
44178
|
+
|
|
44179
|
+
// src/lib/lint-exclusion.ts
|
|
44180
|
+
var BIOME_FILES = ["biome.json", "biome.jsonc"];
|
|
44181
|
+
var KNIP_FILES = [
|
|
44182
|
+
"knip.json",
|
|
44183
|
+
"knip.jsonc",
|
|
44184
|
+
".knip.json",
|
|
44185
|
+
".knip.jsonc",
|
|
44186
|
+
"knip.ts",
|
|
44187
|
+
"knip.js",
|
|
44188
|
+
"knip.config.ts",
|
|
44189
|
+
"knip.config.js"
|
|
44190
|
+
];
|
|
44191
|
+
var MAX_BIOME_CONFIG_READS = 32;
|
|
44192
|
+
var MAX_EXAMPLES = 5;
|
|
44193
|
+
var SCRIPT = /\.[cm]?[jt]sx?$/i;
|
|
44194
|
+
var BIOME_ASSET = /\.(?:[cm]?[jt]sx?|jsonc?|css|graphql|gql)$/i;
|
|
44195
|
+
var OTHER_LINTERS = [
|
|
44196
|
+
"eslint.config.js",
|
|
44197
|
+
"eslint.config.mjs",
|
|
44198
|
+
"eslint.config.ts",
|
|
44199
|
+
".eslintrc.json",
|
|
44200
|
+
".eslintrc.cjs",
|
|
44201
|
+
".oxlintrc.json"
|
|
44202
|
+
];
|
|
44203
|
+
async function inspectHarnessLintExclusion(root) {
|
|
44204
|
+
const checks = [];
|
|
44205
|
+
const biome = BIOME_FILES.find((name) => existsSync(join(root, name)));
|
|
44206
|
+
const knip = KNIP_FILES.find((name) => existsSync(join(root, name)));
|
|
44207
|
+
const other = OTHER_LINTERS.find((name) => existsSync(join(root, name)));
|
|
44208
|
+
const packageKnip = knip === void 0 ? await readPackageKnip(root) : void 0;
|
|
44209
|
+
if (biome === void 0 && knip === void 0 && packageKnip === void 0 && other === void 0) {
|
|
44210
|
+
return [{ name: "lint boundary", ok: true, status: "pass", message: "no analyzer config found" }];
|
|
44211
|
+
}
|
|
44212
|
+
const owned = await analyzerPaths(root);
|
|
44213
|
+
if (biome !== void 0) {
|
|
44214
|
+
const scope = await resolveBiomeIncludes(root, biome);
|
|
44215
|
+
checks.push(owned.kind === "failure" ? manual("lint boundary", biome, owned.reason) : scope.kind === "failure" ? manual("lint boundary", biome, scope.reason) : inspectBiome(biome, owned.paths, scope.includes));
|
|
44216
|
+
} else if (other !== void 0) {
|
|
44217
|
+
checks.push(manual("lint boundary", other, "this analyzer configuration needs manual inspection"));
|
|
44218
|
+
}
|
|
44219
|
+
if (knip !== void 0 || packageKnip !== void 0) {
|
|
44220
|
+
const file2 = knip ?? "package.json";
|
|
44221
|
+
checks.push(owned.kind === "failure" ? manual("knip boundary", file2, owned.reason) : await inspectKnip(root, file2, owned.paths.filter((path3) => SCRIPT.test(path3)), packageKnip));
|
|
44222
|
+
}
|
|
44223
|
+
return checks;
|
|
44224
|
+
}
|
|
44225
|
+
async function analyzerPaths(root) {
|
|
44226
|
+
const owned = await ownedInstallPaths(root);
|
|
44227
|
+
if (owned === void 0) return { kind: "failure", reason: "ownership unknown: no valid manifest or receipt" };
|
|
44228
|
+
const paths = [];
|
|
44229
|
+
try {
|
|
44230
|
+
const canonicalRoot = await realpath(root);
|
|
44231
|
+
for (const path3 of [...owned].sort()) {
|
|
44232
|
+
if (isCoOwned(path3) || classifyMaterialized(path3) !== "derived" || !BIOME_ASSET.test(path3)) continue;
|
|
44233
|
+
const full = join(root, path3);
|
|
44234
|
+
if (!existsSync(full)) continue;
|
|
44235
|
+
if (!isInside(canonicalRoot, await realpath(full))) {
|
|
44236
|
+
return { kind: "failure", reason: `owned path resolves outside the project: ${path3}` };
|
|
44237
|
+
}
|
|
44238
|
+
if ((await lstat(full)).isFile()) paths.push(path3);
|
|
44239
|
+
}
|
|
44240
|
+
} catch {
|
|
44241
|
+
return { kind: "failure", reason: "cannot inspect owned analyzer files" };
|
|
44242
|
+
}
|
|
44243
|
+
return { kind: "paths", paths };
|
|
44244
|
+
}
|
|
44245
|
+
function inspectBiome(file2, paths, includes) {
|
|
44246
|
+
const exposed = [];
|
|
44247
|
+
for (const path3 of paths) {
|
|
44248
|
+
const scope = harnessCanEnter(path3, includes);
|
|
44249
|
+
if (scope.kind === "failure") return manual("lint boundary", file2, scope.reason);
|
|
44250
|
+
if (scope.included) exposed.push(path3);
|
|
44251
|
+
}
|
|
44252
|
+
return boundary("lint boundary", file2, exposed, "files.includes", true);
|
|
44253
|
+
}
|
|
44254
|
+
async function readPackageKnip(root) {
|
|
44255
|
+
if (!existsSync(join(root, "package.json"))) return void 0;
|
|
44256
|
+
const parsed = await readAnalyzerConfig(root, "package.json");
|
|
44257
|
+
return parsed.kind === "parsed" && isRecord6(parsed.value) ? parsed.value.knip : void 0;
|
|
44258
|
+
}
|
|
44259
|
+
async function readAnalyzerConfig(root, file2) {
|
|
44260
|
+
try {
|
|
44261
|
+
const canonicalRoot = await realpath(root);
|
|
44262
|
+
const path3 = await realpath(join(root, file2));
|
|
44263
|
+
if (!isInside(canonicalRoot, path3)) return { kind: "failure", reason: "config resolves outside the project" };
|
|
44264
|
+
return { kind: "parsed", value: JSON.parse(await readFile(path3, "utf8")) };
|
|
44265
|
+
} catch {
|
|
44266
|
+
return { kind: "failure", reason: "config is unreadable or not plain JSON" };
|
|
44267
|
+
}
|
|
44268
|
+
}
|
|
44269
|
+
async function inspectKnip(root, file2, paths, embedded) {
|
|
44270
|
+
if (!file2.endsWith(".json") && !file2.endsWith(".jsonc")) {
|
|
44271
|
+
return manual("knip boundary", file2, "executable configuration is not evaluated");
|
|
44272
|
+
}
|
|
44273
|
+
const read = embedded === void 0 ? await readAnalyzerConfig(root, file2) : { kind: "parsed", value: embedded };
|
|
44274
|
+
if (read.kind === "failure") return manual("knip boundary", file2, read.reason);
|
|
44275
|
+
if (!isRecord6(read.value)) return manual("knip boundary", file2, "config must be an object");
|
|
44276
|
+
const config2 = read.value;
|
|
44277
|
+
const unsupported = Object.keys(config2).some((key) => !["$schema", "ignore", "ignoreFiles"].includes(key));
|
|
44278
|
+
const ignore = stringArray(config2.ignore);
|
|
44279
|
+
const unused = stringArray(config2.ignoreFiles);
|
|
44280
|
+
if (unsupported || ignore === "invalid" || unused === "invalid" || [...ignore ?? [], ...unused ?? []].some((pattern2) => pattern2.startsWith("!") || pattern2.endsWith("!") || pattern2.trim() === "")) {
|
|
44281
|
+
return manual("knip boundary", file2, "unsupported static config or mode-specific patterns; inspect manually");
|
|
44282
|
+
}
|
|
44283
|
+
try {
|
|
44284
|
+
const matches = (0, import_picomatch.default)([...ignore ?? []], { dot: true });
|
|
44285
|
+
const check3 = boundary(
|
|
44286
|
+
"knip boundary",
|
|
44287
|
+
file2,
|
|
44288
|
+
paths.filter((path3) => !matches(path3)),
|
|
44289
|
+
file2 === "package.json" ? "knip.ignore" : "ignore",
|
|
44290
|
+
false
|
|
44291
|
+
);
|
|
44292
|
+
return unused !== void 0 && check3.status === "advisory" ? { ...check3, message: `${check3.message}; ignoreFiles suppresses unused files only` } : check3;
|
|
44293
|
+
} catch {
|
|
44294
|
+
return manual("knip boundary", file2, "invalid ignore patterns");
|
|
44295
|
+
}
|
|
44296
|
+
}
|
|
44297
|
+
function boundary(name, file2, exposed, field11, negate) {
|
|
44298
|
+
if (exposed.length === 0) return { name, ok: true, status: "pass", message: `${file2}: no owned analyzer files exposed` };
|
|
44299
|
+
const sample = exposed.slice(0, MAX_EXAMPLES);
|
|
44300
|
+
const patterns2 = sample.map((path3) => `\`${negate ? "!" : ""}${path3}\``).join(", ");
|
|
44301
|
+
const remainder = exposed.length > MAX_EXAMPLES ? `; inspect the remaining ${exposed.length - MAX_EXAMPLES} owned files in the install manifest` : "";
|
|
44302
|
+
return {
|
|
44303
|
+
name,
|
|
44304
|
+
ok: true,
|
|
44305
|
+
status: "advisory",
|
|
44306
|
+
message: `${file2}: ${exposed.length} owned file(s) lack an explicit analyzer exclusion: ${sample.join(", ")}`,
|
|
44307
|
+
fix: `review ${field11} in ${file2}: exclude ${patterns2}${remainder}` + (negate ? " (keep a positive pattern such as `**` before exclusions; a lone negation matches nothing in Biome)" : "") + "; keep project-owned neighbors in scope"
|
|
44308
|
+
};
|
|
44309
|
+
}
|
|
44310
|
+
async function resolveBiomeIncludes(projectRoot2, configName) {
|
|
44311
|
+
let canonicalRoot;
|
|
44312
|
+
try {
|
|
44313
|
+
canonicalRoot = await realpath(projectRoot2);
|
|
44314
|
+
} catch {
|
|
44315
|
+
return { kind: "failure", reason: "cannot read the project root" };
|
|
44316
|
+
}
|
|
44317
|
+
return readBiomeIncludes(canonicalRoot, join(canonicalRoot, configName), /* @__PURE__ */ new Set(), {
|
|
44318
|
+
remaining: MAX_BIOME_CONFIG_READS
|
|
44319
|
+
});
|
|
44320
|
+
}
|
|
44321
|
+
async function readBiomeIncludes(projectRoot2, configPath, ancestors, budget) {
|
|
44322
|
+
if (budget.remaining === 0) {
|
|
44323
|
+
return { kind: "failure", reason: `extends chain exceeds ${MAX_BIOME_CONFIG_READS} config reads` };
|
|
44324
|
+
}
|
|
44325
|
+
budget.remaining -= 1;
|
|
44326
|
+
const boundedPath = resolve(configPath);
|
|
44327
|
+
if (!isInside(projectRoot2, boundedPath)) {
|
|
44328
|
+
return { kind: "failure", reason: `extended config is outside the project: ${configPath}` };
|
|
44329
|
+
}
|
|
44330
|
+
let canonicalPath;
|
|
44331
|
+
let text8;
|
|
44332
|
+
try {
|
|
44333
|
+
canonicalPath = await realpath(boundedPath);
|
|
44334
|
+
if (!isInside(projectRoot2, canonicalPath)) {
|
|
44335
|
+
return { kind: "failure", reason: `extended config is outside the project: ${configPath}` };
|
|
44336
|
+
}
|
|
44337
|
+
text8 = await readFile(canonicalPath, "utf8");
|
|
44338
|
+
} catch {
|
|
44339
|
+
return { kind: "failure", reason: `cannot read extended config ${displayPath(projectRoot2, boundedPath)}` };
|
|
44340
|
+
}
|
|
44341
|
+
if (ancestors.has(canonicalPath)) {
|
|
44342
|
+
return { kind: "failure", reason: `extends cycle at ${displayPath(projectRoot2, canonicalPath)}` };
|
|
44343
|
+
}
|
|
44344
|
+
const parsed = parseBiomeConfig(text8, displayPath(projectRoot2, canonicalPath));
|
|
44345
|
+
if (parsed.kind === "failure") return parsed;
|
|
44346
|
+
const nextAncestors = new Set(ancestors);
|
|
44347
|
+
nextAncestors.add(canonicalPath);
|
|
44348
|
+
let inheritedIncludes;
|
|
44349
|
+
for (const extendedConfig of parsed.config.extendedConfigs) {
|
|
44350
|
+
const inherited = await readBiomeIncludes(
|
|
44351
|
+
projectRoot2,
|
|
44352
|
+
resolve(dirname(canonicalPath), extendedConfig),
|
|
44353
|
+
nextAncestors,
|
|
44354
|
+
budget
|
|
44355
|
+
);
|
|
44356
|
+
if (inherited.kind === "failure") return inherited;
|
|
44357
|
+
if (inherited.includes !== void 0) inheritedIncludes = inherited.includes;
|
|
44358
|
+
}
|
|
44359
|
+
return {
|
|
44360
|
+
kind: "resolved",
|
|
44361
|
+
includes: parsed.config.includes ?? inheritedIncludes
|
|
44362
|
+
};
|
|
44363
|
+
}
|
|
44364
|
+
function parseBiomeConfig(text8, file2) {
|
|
44365
|
+
let value;
|
|
44366
|
+
try {
|
|
44367
|
+
value = JSON.parse(text8);
|
|
44368
|
+
} catch {
|
|
44369
|
+
return { kind: "failure", reason: `${file2} is not plain JSON` };
|
|
44370
|
+
}
|
|
44371
|
+
if (!isRecord6(value)) return { kind: "failure", reason: `${file2} does not contain a JSON object` };
|
|
44372
|
+
const extendedConfigs = extendedConfigList(value.extends);
|
|
44373
|
+
if (extendedConfigs === "invalid") {
|
|
44374
|
+
return { kind: "failure", reason: `${file2} has an invalid extends value` };
|
|
44375
|
+
}
|
|
44376
|
+
const files = value.files;
|
|
44377
|
+
if (!isAbsent(files) && !isRecord6(files)) {
|
|
44378
|
+
return { kind: "failure", reason: `${file2} has an invalid files value` };
|
|
44379
|
+
}
|
|
44380
|
+
const includesValue = isRecord6(files) ? files.includes : void 0;
|
|
44381
|
+
const includes = stringArray(includesValue);
|
|
44382
|
+
if (includes === "invalid") {
|
|
44383
|
+
return { kind: "failure", reason: `${file2} has an invalid files.includes value` };
|
|
44384
|
+
}
|
|
44385
|
+
return {
|
|
44386
|
+
kind: "parsed",
|
|
44387
|
+
config: {
|
|
44388
|
+
extendedConfigs: extendedConfigs ?? [],
|
|
44389
|
+
includes
|
|
44390
|
+
}
|
|
44391
|
+
};
|
|
44392
|
+
}
|
|
44393
|
+
function extendedConfigList(value) {
|
|
44394
|
+
if (isAbsent(value)) return void 0;
|
|
44395
|
+
if (typeof value === "string") return [value];
|
|
44396
|
+
return stringArray(value);
|
|
44397
|
+
}
|
|
44398
|
+
function stringArray(value) {
|
|
44399
|
+
if (isAbsent(value)) return void 0;
|
|
44400
|
+
if (!Array.isArray(value) || !value.every((entry) => typeof entry === "string")) return "invalid";
|
|
44401
|
+
return value;
|
|
44402
|
+
}
|
|
44403
|
+
function harnessCanEnter(path3, includes) {
|
|
44404
|
+
if (includes === void 0) return { kind: "scope", included: true };
|
|
44405
|
+
let included = false;
|
|
44406
|
+
for (const entry of includes) {
|
|
44407
|
+
const parsed = parseInclude(entry);
|
|
44408
|
+
if (parsed === void 0) {
|
|
44409
|
+
return { kind: "failure", reason: `files.includes contains an empty pattern: ${JSON.stringify(entry)}` };
|
|
44410
|
+
}
|
|
44411
|
+
try {
|
|
44412
|
+
const matches = (0, import_picomatch.default)(parsed.pattern, { dot: true });
|
|
44413
|
+
const segments2 = path3.split("/");
|
|
44414
|
+
const candidates = segments2.map((_, index) => segments2.slice(0, index + 1).join("/"));
|
|
44415
|
+
if (candidates.some((candidate) => matches(candidate))) included = !parsed.excluded;
|
|
44416
|
+
} catch {
|
|
44417
|
+
return { kind: "failure", reason: `files.includes contains an invalid pattern: ${entry}` };
|
|
44418
|
+
}
|
|
44419
|
+
}
|
|
44420
|
+
return { kind: "scope", included };
|
|
44421
|
+
}
|
|
44422
|
+
function parseInclude(entry) {
|
|
44423
|
+
let pattern2 = entry.trim();
|
|
44424
|
+
const excluded = pattern2.startsWith("!");
|
|
44425
|
+
if (pattern2.startsWith("!!")) pattern2 = pattern2.slice(2);
|
|
44426
|
+
else if (excluded) pattern2 = pattern2.slice(1);
|
|
44427
|
+
if (pattern2.startsWith("./")) pattern2 = pattern2.slice(2);
|
|
44428
|
+
return pattern2 === "" ? void 0 : { excluded, pattern: pattern2 };
|
|
44429
|
+
}
|
|
44430
|
+
function isRecord6(value) {
|
|
44431
|
+
return Object.prototype.toString.call(value) === "[object Object]";
|
|
44432
|
+
}
|
|
44433
|
+
function isAbsent(value) {
|
|
44434
|
+
return value === void 0 || Object.prototype.toString.call(value) === "[object Null]";
|
|
44435
|
+
}
|
|
44436
|
+
function isInside(root, candidate) {
|
|
44437
|
+
const path3 = relative(root, candidate);
|
|
44438
|
+
return path3 === "" || !isAbsolute(path3) && path3 !== ".." && !path3.startsWith(`..${sep}`);
|
|
44439
|
+
}
|
|
44440
|
+
function displayPath(root, path3) {
|
|
44441
|
+
const displayed = relative(root, path3);
|
|
44442
|
+
return displayed === "" ? "." : displayed;
|
|
44443
|
+
}
|
|
44444
|
+
function manual(name, file2, reason2) {
|
|
44445
|
+
return {
|
|
44446
|
+
name,
|
|
44447
|
+
ok: true,
|
|
44448
|
+
status: "unknown",
|
|
44449
|
+
message: `${file2}: ${reason2}`,
|
|
44450
|
+
fix: "inspect analyzer scope manually for attested harness assets; keep project-owned files in scope"
|
|
44451
|
+
};
|
|
44452
|
+
}
|
|
44453
|
+
|
|
44014
44454
|
// ../../node_modules/.pnpm/@clack+prompts@1.5.0/node_modules/@clack/prompts/dist/index.mjs
|
|
44015
44455
|
init_esm_shims();
|
|
44016
44456
|
|
|
@@ -45770,7 +46210,7 @@ async function readOrUndefined2(path3) {
|
|
|
45770
46210
|
return void 0;
|
|
45771
46211
|
}
|
|
45772
46212
|
}
|
|
45773
|
-
function
|
|
46213
|
+
function isRecord7(value) {
|
|
45774
46214
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
45775
46215
|
}
|
|
45776
46216
|
async function readHarnessMeta(skillDir) {
|
|
@@ -45778,7 +46218,7 @@ async function readHarnessMeta(skillDir) {
|
|
|
45778
46218
|
if (text8 === void 0) return {};
|
|
45779
46219
|
try {
|
|
45780
46220
|
const parsed = (0, import_yaml4.parse)(text8);
|
|
45781
|
-
if (
|
|
46221
|
+
if (isRecord7(parsed)) return parsed;
|
|
45782
46222
|
} catch {
|
|
45783
46223
|
}
|
|
45784
46224
|
return {};
|
|
@@ -45981,184 +46421,6 @@ async function smokeInstalledHook(hookPath, runtime2) {
|
|
|
45981
46421
|
}
|
|
45982
46422
|
}
|
|
45983
46423
|
|
|
45984
|
-
// src/lib/lint-exclusion.ts
|
|
45985
|
-
init_esm_shims();
|
|
45986
|
-
var import_picomatch = __toESM(require_picomatch2());
|
|
45987
|
-
var HARNESS_LINT_EXCLUSION = "!.claude";
|
|
45988
|
-
var BIOME_FILES = ["biome.json", "biome.jsonc"];
|
|
45989
|
-
var HARNESS_PROBES = [".claude", ".claude/workflows/autopilot.workflow.js"];
|
|
45990
|
-
var MAX_BIOME_CONFIG_READS = 32;
|
|
45991
|
-
var OTHER_LINTERS = [
|
|
45992
|
-
"eslint.config.js",
|
|
45993
|
-
"eslint.config.mjs",
|
|
45994
|
-
"eslint.config.ts",
|
|
45995
|
-
".eslintrc.json",
|
|
45996
|
-
".eslintrc.cjs",
|
|
45997
|
-
".oxlintrc.json"
|
|
45998
|
-
];
|
|
45999
|
-
async function inspectHarnessLintExclusion(projectRoot2) {
|
|
46000
|
-
const biome = BIOME_FILES.map((name) => join(projectRoot2, name)).find((path3) => existsSync(path3));
|
|
46001
|
-
if (biome !== void 0) {
|
|
46002
|
-
const name = relative(projectRoot2, biome);
|
|
46003
|
-
const scope = await resolveBiomeIncludes(projectRoot2, name);
|
|
46004
|
-
if (scope.kind === "failure") return manual(name, scope.reason);
|
|
46005
|
-
const harnessScope = harnessCanEnter(scope.includes);
|
|
46006
|
-
if (harnessScope.kind === "failure") return manual(name, harnessScope.reason);
|
|
46007
|
-
if (!harnessScope.included) {
|
|
46008
|
-
return { kind: "excluded", file: name };
|
|
46009
|
-
}
|
|
46010
|
-
return {
|
|
46011
|
-
kind: "missing",
|
|
46012
|
-
file: name,
|
|
46013
|
-
instruction: `add \`${HARNESS_LINT_EXCLUSION}\` to files.includes in ${name} (keep a positive pattern such as \`**\` before it \u2014 a lone negation matches nothing in Biome)`
|
|
46014
|
-
};
|
|
46015
|
-
}
|
|
46016
|
-
const other = OTHER_LINTERS.find((name) => existsSync(join(projectRoot2, name)));
|
|
46017
|
-
if (other !== void 0) {
|
|
46018
|
-
return manual(other, "this linter is configured in code");
|
|
46019
|
-
}
|
|
46020
|
-
return { kind: "no-linter" };
|
|
46021
|
-
}
|
|
46022
|
-
async function resolveBiomeIncludes(projectRoot2, configName) {
|
|
46023
|
-
let canonicalRoot;
|
|
46024
|
-
try {
|
|
46025
|
-
canonicalRoot = await realpath(projectRoot2);
|
|
46026
|
-
} catch {
|
|
46027
|
-
return { kind: "failure", reason: "cannot read the project root" };
|
|
46028
|
-
}
|
|
46029
|
-
return readBiomeIncludes(canonicalRoot, join(canonicalRoot, configName), /* @__PURE__ */ new Set(), {
|
|
46030
|
-
remaining: MAX_BIOME_CONFIG_READS
|
|
46031
|
-
});
|
|
46032
|
-
}
|
|
46033
|
-
async function readBiomeIncludes(projectRoot2, configPath, ancestors, budget) {
|
|
46034
|
-
if (budget.remaining === 0) {
|
|
46035
|
-
return { kind: "failure", reason: `extends chain exceeds ${MAX_BIOME_CONFIG_READS} config reads` };
|
|
46036
|
-
}
|
|
46037
|
-
budget.remaining -= 1;
|
|
46038
|
-
const boundedPath = resolve(configPath);
|
|
46039
|
-
if (!isInside(projectRoot2, boundedPath)) {
|
|
46040
|
-
return { kind: "failure", reason: `extended config is outside the project: ${configPath}` };
|
|
46041
|
-
}
|
|
46042
|
-
let canonicalPath;
|
|
46043
|
-
let text8;
|
|
46044
|
-
try {
|
|
46045
|
-
canonicalPath = await realpath(boundedPath);
|
|
46046
|
-
if (!isInside(projectRoot2, canonicalPath)) {
|
|
46047
|
-
return { kind: "failure", reason: `extended config is outside the project: ${configPath}` };
|
|
46048
|
-
}
|
|
46049
|
-
text8 = await readFile(canonicalPath, "utf8");
|
|
46050
|
-
} catch {
|
|
46051
|
-
return { kind: "failure", reason: `cannot read extended config ${displayPath(projectRoot2, boundedPath)}` };
|
|
46052
|
-
}
|
|
46053
|
-
if (ancestors.has(canonicalPath)) {
|
|
46054
|
-
return { kind: "failure", reason: `extends cycle at ${displayPath(projectRoot2, canonicalPath)}` };
|
|
46055
|
-
}
|
|
46056
|
-
const parsed = parseBiomeConfig(text8, displayPath(projectRoot2, canonicalPath));
|
|
46057
|
-
if (parsed.kind === "failure") return parsed;
|
|
46058
|
-
const nextAncestors = new Set(ancestors);
|
|
46059
|
-
nextAncestors.add(canonicalPath);
|
|
46060
|
-
let inheritedIncludes;
|
|
46061
|
-
for (const extendedConfig of parsed.config.extendedConfigs) {
|
|
46062
|
-
const inherited = await readBiomeIncludes(
|
|
46063
|
-
projectRoot2,
|
|
46064
|
-
resolve(dirname(canonicalPath), extendedConfig),
|
|
46065
|
-
nextAncestors,
|
|
46066
|
-
budget
|
|
46067
|
-
);
|
|
46068
|
-
if (inherited.kind === "failure") return inherited;
|
|
46069
|
-
if (inherited.includes !== void 0) inheritedIncludes = inherited.includes;
|
|
46070
|
-
}
|
|
46071
|
-
return {
|
|
46072
|
-
kind: "resolved",
|
|
46073
|
-
includes: parsed.config.includes ?? inheritedIncludes
|
|
46074
|
-
};
|
|
46075
|
-
}
|
|
46076
|
-
function parseBiomeConfig(text8, file2) {
|
|
46077
|
-
let value;
|
|
46078
|
-
try {
|
|
46079
|
-
value = JSON.parse(text8);
|
|
46080
|
-
} catch {
|
|
46081
|
-
return { kind: "failure", reason: `${file2} is not plain JSON` };
|
|
46082
|
-
}
|
|
46083
|
-
if (!isRecord7(value)) return { kind: "failure", reason: `${file2} does not contain a JSON object` };
|
|
46084
|
-
const extendedConfigs = extendedConfigList(value.extends);
|
|
46085
|
-
if (extendedConfigs === "invalid") {
|
|
46086
|
-
return { kind: "failure", reason: `${file2} has an invalid extends value` };
|
|
46087
|
-
}
|
|
46088
|
-
const files = value.files;
|
|
46089
|
-
if (!isAbsent(files) && !isRecord7(files)) {
|
|
46090
|
-
return { kind: "failure", reason: `${file2} has an invalid files value` };
|
|
46091
|
-
}
|
|
46092
|
-
const includesValue = isRecord7(files) ? files.includes : void 0;
|
|
46093
|
-
const includes = stringArray(includesValue);
|
|
46094
|
-
if (includes === "invalid") {
|
|
46095
|
-
return { kind: "failure", reason: `${file2} has an invalid files.includes value` };
|
|
46096
|
-
}
|
|
46097
|
-
return {
|
|
46098
|
-
kind: "parsed",
|
|
46099
|
-
config: {
|
|
46100
|
-
extendedConfigs: extendedConfigs ?? [],
|
|
46101
|
-
includes
|
|
46102
|
-
}
|
|
46103
|
-
};
|
|
46104
|
-
}
|
|
46105
|
-
function extendedConfigList(value) {
|
|
46106
|
-
if (isAbsent(value)) return void 0;
|
|
46107
|
-
if (typeof value === "string") return [value];
|
|
46108
|
-
return stringArray(value);
|
|
46109
|
-
}
|
|
46110
|
-
function stringArray(value) {
|
|
46111
|
-
if (isAbsent(value)) return void 0;
|
|
46112
|
-
if (!Array.isArray(value) || !value.every((entry) => typeof entry === "string")) return "invalid";
|
|
46113
|
-
return value;
|
|
46114
|
-
}
|
|
46115
|
-
function harnessCanEnter(includes) {
|
|
46116
|
-
if (includes === void 0) return { kind: "scope", included: true };
|
|
46117
|
-
let included = false;
|
|
46118
|
-
for (const entry of includes) {
|
|
46119
|
-
const parsed = parseInclude(entry);
|
|
46120
|
-
if (parsed === void 0) {
|
|
46121
|
-
return { kind: "failure", reason: `files.includes contains an empty pattern: ${JSON.stringify(entry)}` };
|
|
46122
|
-
}
|
|
46123
|
-
try {
|
|
46124
|
-
const matches = (0, import_picomatch.default)(parsed.pattern, { dot: true });
|
|
46125
|
-
if (HARNESS_PROBES.some((probe) => matches(probe))) included = !parsed.excluded;
|
|
46126
|
-
} catch {
|
|
46127
|
-
return { kind: "failure", reason: `files.includes contains an invalid pattern: ${entry}` };
|
|
46128
|
-
}
|
|
46129
|
-
}
|
|
46130
|
-
return { kind: "scope", included };
|
|
46131
|
-
}
|
|
46132
|
-
function parseInclude(entry) {
|
|
46133
|
-
let pattern2 = entry.trim();
|
|
46134
|
-
const excluded = pattern2.startsWith("!");
|
|
46135
|
-
if (pattern2.startsWith("!!")) pattern2 = pattern2.slice(2);
|
|
46136
|
-
else if (excluded) pattern2 = pattern2.slice(1);
|
|
46137
|
-
if (pattern2.startsWith("./")) pattern2 = pattern2.slice(2);
|
|
46138
|
-
return pattern2 === "" ? void 0 : { excluded, pattern: pattern2 };
|
|
46139
|
-
}
|
|
46140
|
-
function isRecord7(value) {
|
|
46141
|
-
return Object.prototype.toString.call(value) === "[object Object]";
|
|
46142
|
-
}
|
|
46143
|
-
function isAbsent(value) {
|
|
46144
|
-
return value === void 0 || Object.prototype.toString.call(value) === "[object Null]";
|
|
46145
|
-
}
|
|
46146
|
-
function isInside(root, candidate) {
|
|
46147
|
-
const path3 = relative(root, candidate);
|
|
46148
|
-
return path3 === "" || !isAbsolute(path3) && path3 !== ".." && !path3.startsWith(`..${sep}`);
|
|
46149
|
-
}
|
|
46150
|
-
function displayPath(root, path3) {
|
|
46151
|
-
const displayed = relative(root, path3);
|
|
46152
|
-
return displayed === "" ? "." : displayed;
|
|
46153
|
-
}
|
|
46154
|
-
function manual(file2, why2) {
|
|
46155
|
-
return {
|
|
46156
|
-
kind: "manual",
|
|
46157
|
-
file: file2,
|
|
46158
|
-
instruction: `${why2}: add \`${HARNESS_LINT_EXCLUSION}\` to ${file2} (after a positive pattern such as \`**\`) so the harness is not linted as project source`
|
|
46159
|
-
};
|
|
46160
|
-
}
|
|
46161
|
-
|
|
46162
46424
|
// src/lib/plugin-cache.ts
|
|
46163
46425
|
init_esm_shims();
|
|
46164
46426
|
function wiredHooks(manifest) {
|
|
@@ -46712,14 +46974,10 @@ var claudeAdapter = {
|
|
|
46712
46974
|
enabledPacks: ctx.enabledPacks,
|
|
46713
46975
|
channel: ctx.source
|
|
46714
46976
|
});
|
|
46715
|
-
const lint = await inspectHarnessLintExclusion(ctx.installRoot);
|
|
46716
|
-
const lintLine = lint.kind === "excluded" ? `${lint.file}: .claude excluded from lint` : lint.kind === "no-linter" ? "lint: no linter config found, nothing to exclude" : `lint: ${lint.file} lints .claude as project source`;
|
|
46717
|
-
if (lint.kind === "missing" || lint.kind === "manual") nextSteps.push(lint.instruction);
|
|
46718
46977
|
return {
|
|
46719
46978
|
statusLines: [
|
|
46720
46979
|
status3,
|
|
46721
|
-
`CLAUDE.md: ${docResult}
|
|
46722
|
-
lintLine
|
|
46980
|
+
`CLAUDE.md: ${docResult}`
|
|
46723
46981
|
],
|
|
46724
46982
|
nextSteps
|
|
46725
46983
|
};
|
|
@@ -47211,14 +47469,7 @@ function buildDefaultConfig(seed) {
|
|
|
47211
47469
|
const config2 = {
|
|
47212
47470
|
packs: {},
|
|
47213
47471
|
stack: { ...seed.stack },
|
|
47214
|
-
paths:
|
|
47215
|
-
business: "apps/*/src/**",
|
|
47216
|
-
tests: "apps/*/src/**/*.test.{ts,tsx}",
|
|
47217
|
-
spikes: "apps/*/scripts/spike-*",
|
|
47218
|
-
serverActions: "apps/*/src/app/(api|actions)/**",
|
|
47219
|
-
contracts: "apps/*/src/lib/contracts/**",
|
|
47220
|
-
e2e: "apps/*/tests/e2e/**"
|
|
47221
|
-
},
|
|
47472
|
+
paths: DEFAULT_PROJECT_PATHS,
|
|
47222
47473
|
commands: commandsFor(seed.stack),
|
|
47223
47474
|
modes: { tdd: "auto", codeReview: "auto" }
|
|
47224
47475
|
};
|
|
@@ -47361,6 +47612,10 @@ async function init(args) {
|
|
|
47361
47612
|
line(`${c.green(glyph.check)} ${c.dim("transaction".padEnd(18))}${prepared.receipt.files.length} owned files committed + receipt written`);
|
|
47362
47613
|
claimOwnedPaths(projectRoot2, prepared.receipt.files.map((file2) => file2.path));
|
|
47363
47614
|
reportHiddenByProject(projectRoot2);
|
|
47615
|
+
for (const check3 of await inspectHarnessLintExclusion(projectRoot2)) {
|
|
47616
|
+
line(`${c.dim(check3.name.padEnd(18))}${check3.message}`);
|
|
47617
|
+
if (check3.fix !== void 0) nextSteps.push(check3.fix);
|
|
47618
|
+
}
|
|
47364
47619
|
if (keptByProject.length > 0) {
|
|
47365
47620
|
line(`${c.yellow("!")} ${c.dim("kept".padEnd(18))}${keptByProject.length} skill(s) the project already had, left untouched`);
|
|
47366
47621
|
for (const path3 of keptByProject.slice(0, 5)) line(c.dim(` ${path3}`));
|
|
@@ -48483,7 +48738,7 @@ var FROZEN_MARKER = /frozen legacy (?:snapshot|landing page)/i;
|
|
|
48483
48738
|
var RECENT_LIMIT = 5;
|
|
48484
48739
|
var MAX_TITLE = 200;
|
|
48485
48740
|
var MAX_INPUT2 = 2e6;
|
|
48486
|
-
var
|
|
48741
|
+
var EMPTY2 = Object.freeze({
|
|
48487
48742
|
format: "none",
|
|
48488
48743
|
count: 0,
|
|
48489
48744
|
recent: [],
|
|
@@ -48539,7 +48794,7 @@ function observeDecisions(input2) {
|
|
|
48539
48794
|
liveMonolithEntries
|
|
48540
48795
|
};
|
|
48541
48796
|
}
|
|
48542
|
-
if (monolithEntries.length === 0) return
|
|
48797
|
+
if (monolithEntries.length === 0) return EMPTY2;
|
|
48543
48798
|
return {
|
|
48544
48799
|
format: frozen ? "frozen-monolith" : "live-monolith",
|
|
48545
48800
|
count: monolithEntries.length,
|
|
@@ -49189,149 +49444,6 @@ function judgeLayout(observation3) {
|
|
|
49189
49444
|
]);
|
|
49190
49445
|
}
|
|
49191
49446
|
|
|
49192
|
-
// src/lib/void-migration.ts
|
|
49193
|
-
init_esm_shims();
|
|
49194
|
-
var EMPTY2 = Object.freeze({
|
|
49195
|
-
moved: [],
|
|
49196
|
-
conflicts: [],
|
|
49197
|
-
parked: [],
|
|
49198
|
-
gitignoreBlockRemoved: false
|
|
49199
|
-
});
|
|
49200
|
-
async function freeParkedName(target) {
|
|
49201
|
-
if (!existsSync(`${target}.legacy`)) return `${target}.legacy`;
|
|
49202
|
-
for (let attempt = 2; attempt < 100; attempt += 1) {
|
|
49203
|
-
const candidate = `${target}.legacy.${String(attempt)}`;
|
|
49204
|
-
if (!existsSync(candidate)) return candidate;
|
|
49205
|
-
}
|
|
49206
|
-
return `${target}.legacy.overflow`;
|
|
49207
|
-
}
|
|
49208
|
-
async function mergeInto(source2, destination) {
|
|
49209
|
-
const info = await stat(source2);
|
|
49210
|
-
if (!info.isDirectory()) {
|
|
49211
|
-
if (!existsSync(destination)) {
|
|
49212
|
-
await mkdir(join(destination, ".."), { recursive: true });
|
|
49213
|
-
await rename(source2, destination);
|
|
49214
|
-
return false;
|
|
49215
|
-
}
|
|
49216
|
-
await rename(source2, await freeParkedName(destination));
|
|
49217
|
-
return true;
|
|
49218
|
-
}
|
|
49219
|
-
await mkdir(destination, { recursive: true });
|
|
49220
|
-
let parked = false;
|
|
49221
|
-
for (const entry of await readdir(source2)) {
|
|
49222
|
-
if (await mergeInto(join(source2, entry), join(destination, entry))) parked = true;
|
|
49223
|
-
}
|
|
49224
|
-
await rm(source2, { recursive: true, force: true });
|
|
49225
|
-
return parked;
|
|
49226
|
-
}
|
|
49227
|
-
function planVoidMigration(root) {
|
|
49228
|
-
const movable = [];
|
|
49229
|
-
const conflicts = [];
|
|
49230
|
-
for (const entry of pendingMigrations(root)) {
|
|
49231
|
-
if (existsSync(voidMachinePath(root, entry))) conflicts.push(entry);
|
|
49232
|
-
else movable.push(entry);
|
|
49233
|
-
}
|
|
49234
|
-
return { movable, conflicts };
|
|
49235
|
-
}
|
|
49236
|
-
async function ownedDerivedPaths(root) {
|
|
49237
|
-
const manifestPath = join(root, ...INSTALL_MANIFEST_PATH.split("/"));
|
|
49238
|
-
if (existsSync(manifestPath)) {
|
|
49239
|
-
try {
|
|
49240
|
-
const manifest = parseInstallManifest(await readFile(manifestPath, "utf8"));
|
|
49241
|
-
if (manifest !== void 0) {
|
|
49242
|
-
return new Set(manifest.files.map((file2) => file2.path).filter((path3) => isOwnedDerived(path3)));
|
|
49243
|
-
}
|
|
49244
|
-
} catch {
|
|
49245
|
-
}
|
|
49246
|
-
}
|
|
49247
|
-
const receipt2 = await readInstallReceipt(root);
|
|
49248
|
-
if (receipt2 === void 0) return void 0;
|
|
49249
|
-
return new Set(receipt2.files.map((file2) => file2.path).filter((path3) => isOwnedDerived(path3)));
|
|
49250
|
-
}
|
|
49251
|
-
async function untrackDerived(root, dryRun = false) {
|
|
49252
|
-
const owned = await ownedDerivedPaths(root);
|
|
49253
|
-
if (owned === void 0) {
|
|
49254
|
-
return { untracked: [], error: "no readable install manifest or receipt \u2014 nothing here can be proven harness-owned" };
|
|
49255
|
-
}
|
|
49256
|
-
let listed;
|
|
49257
|
-
try {
|
|
49258
|
-
listed = execFileSync("git", ["ls-files", "-z", "--", ".void", ".claude", ".agents", ".codex"], {
|
|
49259
|
-
cwd: root,
|
|
49260
|
-
encoding: "utf8",
|
|
49261
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
49262
|
-
});
|
|
49263
|
-
} catch {
|
|
49264
|
-
return { untracked: [], error: "not a git repository, or git is unavailable" };
|
|
49265
|
-
}
|
|
49266
|
-
const untracked = listed.split("\0").filter((path3) => path3 !== "" && owned.has(path3.split("\\").join("/")));
|
|
49267
|
-
if (untracked.length === 0 || dryRun) return { untracked };
|
|
49268
|
-
try {
|
|
49269
|
-
for (let index = 0; index < untracked.length; index += 200) {
|
|
49270
|
-
execFileSync("git", ["rm", "--cached", "--quiet", "--", ...untracked.slice(index, index + 200)], {
|
|
49271
|
-
cwd: root,
|
|
49272
|
-
stdio: ["ignore", "ignore", "pipe"]
|
|
49273
|
-
});
|
|
49274
|
-
}
|
|
49275
|
-
} catch (error62) {
|
|
49276
|
-
return { untracked: [], error: error62 instanceof Error ? error62.message.split("\n")[0] ?? "git rm failed" : "git rm failed" };
|
|
49277
|
-
}
|
|
49278
|
-
return { untracked };
|
|
49279
|
-
}
|
|
49280
|
-
async function migrateVoidLayout(root, dryRun = false) {
|
|
49281
|
-
if (!existsSync(join(root, ".void"))) return EMPTY2;
|
|
49282
|
-
const { movable, conflicts } = planVoidMigration(root);
|
|
49283
|
-
if (!dryRun) writeExcludeBlock(root, [...await ownedDerivedPaths(root) ?? []]);
|
|
49284
|
-
const gitignorePath = join(root, ".gitignore");
|
|
49285
|
-
const original = existsSync(gitignorePath) ? await readFile(gitignorePath, "utf8") : "";
|
|
49286
|
-
const stripped = stripManagedBlock(original);
|
|
49287
|
-
const gitignoreBlockRemoved = stripped !== original;
|
|
49288
|
-
const pending = [...movable, ...conflicts].sort();
|
|
49289
|
-
const failed2 = [];
|
|
49290
|
-
if (dryRun) return { moved: pending, conflicts: [], parked: [], gitignoreBlockRemoved };
|
|
49291
|
-
if (pending.length > 0) {
|
|
49292
|
-
await mkdir(voidMachineDir(root), { recursive: true });
|
|
49293
|
-
await mkdir(voidInstalledDir(root), { recursive: true });
|
|
49294
|
-
}
|
|
49295
|
-
const moved = [];
|
|
49296
|
-
const parked = [];
|
|
49297
|
-
for (const entry of pending) {
|
|
49298
|
-
try {
|
|
49299
|
-
const sources = [legacyVoidPath(root, entry), previousMachinePath(root, entry)].filter((source2) => existsSync(source2));
|
|
49300
|
-
if (ownershipOf(entry) === "derived") {
|
|
49301
|
-
for (const source2 of sources) await rm(source2, { recursive: true, force: true });
|
|
49302
|
-
if (sources.length > 0) moved.push(entry);
|
|
49303
|
-
continue;
|
|
49304
|
-
}
|
|
49305
|
-
let touched = false;
|
|
49306
|
-
for (const source2 of sources) {
|
|
49307
|
-
if (await mergeInto(source2, voidMachinePath(root, migratedName(entry)))) touched = true;
|
|
49308
|
-
}
|
|
49309
|
-
if (touched) parked.push(entry);
|
|
49310
|
-
moved.push(entry);
|
|
49311
|
-
} catch {
|
|
49312
|
-
failed2.push(entry);
|
|
49313
|
-
}
|
|
49314
|
-
}
|
|
49315
|
-
try {
|
|
49316
|
-
const previous = join(root, ".void", "local");
|
|
49317
|
-
if (existsSync(previous)) {
|
|
49318
|
-
for (const entry of await readdir(previous)) {
|
|
49319
|
-
await mergeInto(join(previous, entry), voidMachinePath(root, entry));
|
|
49320
|
-
}
|
|
49321
|
-
}
|
|
49322
|
-
} catch {
|
|
49323
|
-
}
|
|
49324
|
-
try {
|
|
49325
|
-
const previous = join(root, ".void", "local");
|
|
49326
|
-
if (existsSync(previous) && (await readdir(previous)).length === 0) {
|
|
49327
|
-
await rm(previous, { recursive: true, force: true });
|
|
49328
|
-
}
|
|
49329
|
-
} catch {
|
|
49330
|
-
}
|
|
49331
|
-
if (gitignoreBlockRemoved) await writeFile(gitignorePath, stripped);
|
|
49332
|
-
return { moved, conflicts: failed2.sort(), parked: parked.sort(), gitignoreBlockRemoved };
|
|
49333
|
-
}
|
|
49334
|
-
|
|
49335
49447
|
// src/commands/self-host.ts
|
|
49336
49448
|
init_esm_shims();
|
|
49337
49449
|
|
|
@@ -50268,18 +50380,7 @@ async function doctor(args) {
|
|
|
50268
50380
|
});
|
|
50269
50381
|
}
|
|
50270
50382
|
}
|
|
50271
|
-
|
|
50272
|
-
const lint = await inspectHarnessLintExclusion(root);
|
|
50273
|
-
checks.push(
|
|
50274
|
-
lint.kind === "excluded" ? { name: "lint boundary", ok: true, message: `${lint.file}: .claude excluded from project lint` } : lint.kind === "no-linter" ? { name: "lint boundary", ok: true, message: "no linter config found, nothing to exclude" } : {
|
|
50275
|
-
name: "lint boundary",
|
|
50276
|
-
ok: true,
|
|
50277
|
-
status: "advisory",
|
|
50278
|
-
message: `${lint.file} lints .claude as project source; harness files are written in engine formats a JS parser rejects`,
|
|
50279
|
-
fix: lint.instruction
|
|
50280
|
-
}
|
|
50281
|
-
);
|
|
50282
|
-
}
|
|
50383
|
+
checks.push(...await inspectHarnessLintExclusion(root));
|
|
50283
50384
|
checks.push(checkEnforceWorkflow(root));
|
|
50284
50385
|
if (claudeDetected && marketplaceInstall) {
|
|
50285
50386
|
if (!skipRemote) {
|
|
@@ -50765,131 +50866,6 @@ async function hydrate(args) {
|
|
|
50765
50866
|
|
|
50766
50867
|
// src/commands/check.ts
|
|
50767
50868
|
init_esm_shims();
|
|
50768
|
-
var GH_REMOTE = {
|
|
50769
|
-
fetchRemoteMarketplace,
|
|
50770
|
-
fetchPinnedPluginVersion,
|
|
50771
|
-
fetchRemotePhilosophy
|
|
50772
|
-
};
|
|
50773
|
-
async function check2(args, options2 = {}) {
|
|
50774
|
-
const doctrine = args.includes("--doctrine");
|
|
50775
|
-
const remote = options2.remote ?? GH_REMOTE;
|
|
50776
|
-
const roots = resolveProjectRoots(options2.cwd);
|
|
50777
|
-
const installRoot = roots.installRoot;
|
|
50778
|
-
const where = remedyPrefix(roots);
|
|
50779
|
-
const repo = await resolveMarketplaceRepo(installRoot);
|
|
50780
|
-
const local = await readLocalConfig(installRoot);
|
|
50781
|
-
banner("check");
|
|
50782
|
-
meta3("marketplace", repo);
|
|
50783
|
-
blank();
|
|
50784
|
-
const marketplace = remote.fetchRemoteMarketplace(repo);
|
|
50785
|
-
if (!marketplace.ok) {
|
|
50786
|
-
status(`could not fetch remote marketplace: ${marketplace.error}`, "err");
|
|
50787
|
-
line(c.dim("verify `gh auth status` and that you have access to the repo."));
|
|
50788
|
-
process.exit(1);
|
|
50789
|
-
}
|
|
50790
|
-
const drift = reportVersionDrift(local, marketplace.value, repo, remote);
|
|
50791
|
-
if (doctrine) {
|
|
50792
|
-
blank();
|
|
50793
|
-
await reportDoctrineDrift(installRoot, where, marketplace.value, repo, remote);
|
|
50794
|
-
}
|
|
50795
|
-
if (drift > 0) {
|
|
50796
|
-
footer(
|
|
50797
|
-
`${c.yellow(`${drift} plugin${drift > 1 ? "s" : ""} behind`)} ${glyph.emdash} run ${where}${c.bold(
|
|
50798
|
-
`${PRODUCT_COMMAND} update`
|
|
50799
|
-
)} ${c.dim("(refreshes the plugin cache + bumps the pins this check measures), then restart Claude Code")}`
|
|
50800
|
-
);
|
|
50801
|
-
} else {
|
|
50802
|
-
footer(c.dim("all up to date"));
|
|
50803
|
-
}
|
|
50804
|
-
}
|
|
50805
|
-
async function resolveMarketplaceRepo(installRoot) {
|
|
50806
|
-
const settings = await readSettings(settingsPathFor(installRoot));
|
|
50807
|
-
const entry = settings.extraKnownMarketplaces?.[MARKETPLACE_NAME];
|
|
50808
|
-
if (entry && typeof entry === "object") {
|
|
50809
|
-
const source2 = entry.source;
|
|
50810
|
-
if (source2?.repo) return source2.repo;
|
|
50811
|
-
}
|
|
50812
|
-
return MARKETPLACE_REPO;
|
|
50813
|
-
}
|
|
50814
|
-
async function readLocalConfig(installRoot) {
|
|
50815
|
-
const configPath = join(installRoot, ".void", "config.json");
|
|
50816
|
-
if (!existsSync(configPath)) return {};
|
|
50817
|
-
try {
|
|
50818
|
-
return JSON.parse(await readFile(configPath, "utf8"));
|
|
50819
|
-
} catch {
|
|
50820
|
-
return {};
|
|
50821
|
-
}
|
|
50822
|
-
}
|
|
50823
|
-
function reportVersionDrift(local, marketplace, marketplaceRepo, remote) {
|
|
50824
|
-
const localVersions = {
|
|
50825
|
-
[CORE_PLUGIN_NAME]: local.core
|
|
50826
|
-
};
|
|
50827
|
-
for (const pack2 of PACKS) {
|
|
50828
|
-
localVersions[pack2.name] = local.packs?.[`@voidcorp/${pack2.name}`];
|
|
50829
|
-
}
|
|
50830
|
-
let drift = 0;
|
|
50831
|
-
for (const plugin of marketplace.plugins) {
|
|
50832
|
-
const declaredRaw = localVersions[plugin.name];
|
|
50833
|
-
const localStr = declaredRaw ? normalizeVersion(declaredRaw) : glyph.emdash;
|
|
50834
|
-
const remoteFetch = remote.fetchPinnedPluginVersion(plugin, marketplaceRepo);
|
|
50835
|
-
if (!remoteFetch.ok) {
|
|
50836
|
-
row({ mark: "info", label: plugin.name, versions: [localStr, glyph.emdash], suffix: c.dim(remoteFetch.error) });
|
|
50837
|
-
continue;
|
|
50838
|
-
}
|
|
50839
|
-
const remoteStr = remoteFetch.value;
|
|
50840
|
-
if (!declaredRaw) {
|
|
50841
|
-
row({
|
|
50842
|
-
mark: "info",
|
|
50843
|
-
label: plugin.name,
|
|
50844
|
-
versions: [localStr, remoteStr],
|
|
50845
|
-
suffix: c.dim("not installed")
|
|
50846
|
-
});
|
|
50847
|
-
} else if (compareVersions(localStr, remoteStr) < 0) {
|
|
50848
|
-
drift += 1;
|
|
50849
|
-
row({
|
|
50850
|
-
mark: "warn",
|
|
50851
|
-
label: plugin.name,
|
|
50852
|
-
versions: [localStr, remoteStr],
|
|
50853
|
-
suffix: c.yellow("update available")
|
|
50854
|
-
});
|
|
50855
|
-
} else {
|
|
50856
|
-
row({
|
|
50857
|
-
mark: "ok",
|
|
50858
|
-
label: plugin.name,
|
|
50859
|
-
versions: [localStr, remoteStr],
|
|
50860
|
-
suffix: c.dim("up to date")
|
|
50861
|
-
});
|
|
50862
|
-
}
|
|
50863
|
-
}
|
|
50864
|
-
return drift;
|
|
50865
|
-
}
|
|
50866
|
-
async function reportDoctrineDrift(installRoot, where, marketplace, marketplaceRepo, remote) {
|
|
50867
|
-
const migrated = join(installRoot, ".void", "installed", "PHILOSOPHY.md");
|
|
50868
|
-
const localPath = existsSync(migrated) ? migrated : join(installRoot, ".void", "PHILOSOPHY.md");
|
|
50869
|
-
if (!existsSync(localPath)) {
|
|
50870
|
-
status(`PHILOSOPHY.md missing locally \u2014 run ${where}\`${PRODUCT_COMMAND} init\` to install.`, "warn");
|
|
50871
|
-
return;
|
|
50872
|
-
}
|
|
50873
|
-
const localText = await readFile(localPath, "utf8");
|
|
50874
|
-
const fetched = remote.fetchRemotePhilosophy(marketplace, CORE_PLUGIN_NAME, marketplaceRepo);
|
|
50875
|
-
if (!fetched.ok) {
|
|
50876
|
-
status(`could not fetch remote PHILOSOPHY.md: ${fetched.error}`, "warn");
|
|
50877
|
-
return;
|
|
50878
|
-
}
|
|
50879
|
-
if (normalizeNewlines(localText) === normalizeNewlines(fetched.value)) {
|
|
50880
|
-
status(`PHILOSOPHY.md ${c.dim("in sync")}`);
|
|
50881
|
-
return;
|
|
50882
|
-
}
|
|
50883
|
-
const localLines = localText.split("\n").length;
|
|
50884
|
-
const remoteLines = fetched.value.split("\n").length;
|
|
50885
|
-
status(
|
|
50886
|
-
`PHILOSOPHY.md drift (local ${localLines}L, remote ${remoteLines}L) \u2014 run ${where}\`${PRODUCT_COMMAND} init\` to overwrite`,
|
|
50887
|
-
"warn"
|
|
50888
|
-
);
|
|
50889
|
-
}
|
|
50890
|
-
function normalizeNewlines(s) {
|
|
50891
|
-
return s.replace(/\r\n/g, "\n").trimEnd();
|
|
50892
|
-
}
|
|
50893
50869
|
|
|
50894
50870
|
// src/commands/update.ts
|
|
50895
50871
|
init_esm_shims();
|
|
@@ -51149,7 +51125,7 @@ async function update(args) {
|
|
|
51149
51125
|
}
|
|
51150
51126
|
banner("update");
|
|
51151
51127
|
renderLegacyRegistryNotice(legacyRegistryNotice);
|
|
51152
|
-
const repo = await
|
|
51128
|
+
const repo = await resolveMarketplaceRepo(projectRoot2);
|
|
51153
51129
|
meta3("marketplace", repo);
|
|
51154
51130
|
const remote = fetchRemoteMarketplace(repo);
|
|
51155
51131
|
if (!remote.ok) {
|
|
@@ -51505,7 +51481,7 @@ async function bumpPins(projectRoot2, head, dryRun) {
|
|
|
51505
51481
|
`);
|
|
51506
51482
|
return changes.length;
|
|
51507
51483
|
}
|
|
51508
|
-
async function
|
|
51484
|
+
async function resolveMarketplaceRepo(projectRoot2) {
|
|
51509
51485
|
const settings = await readSettings(settingsPathFor(projectRoot2));
|
|
51510
51486
|
const entry = settings.extraKnownMarketplaces?.[MARKETPLACE_NAME];
|
|
51511
51487
|
if (entry && typeof entry === "object") {
|
|
@@ -51515,6 +51491,166 @@ async function resolveMarketplaceRepo2(projectRoot2) {
|
|
|
51515
51491
|
return MARKETPLACE_REPO;
|
|
51516
51492
|
}
|
|
51517
51493
|
|
|
51494
|
+
// src/commands/check.ts
|
|
51495
|
+
var GH_REMOTE = {
|
|
51496
|
+
fetchRemoteMarketplace,
|
|
51497
|
+
fetchPinnedPluginVersion,
|
|
51498
|
+
fetchRemotePhilosophy
|
|
51499
|
+
};
|
|
51500
|
+
async function check2(args, options2 = {}) {
|
|
51501
|
+
const doctrine = args.includes("--doctrine");
|
|
51502
|
+
const remote = options2.remote ?? GH_REMOTE;
|
|
51503
|
+
const roots = resolveProjectRoots(options2.cwd);
|
|
51504
|
+
const installRoot = roots.installRoot;
|
|
51505
|
+
const where = remedyPrefix(roots);
|
|
51506
|
+
const receipt2 = await readInstallReceipt(installRoot);
|
|
51507
|
+
const hasManifest = existsSync(join(installRoot, INSTALL_MANIFEST_PATH));
|
|
51508
|
+
const unknownChannel = receipt2 === void 0 && !hasManifest && await receiptEvidenceExists(installRoot);
|
|
51509
|
+
const route = updateRouteFor(receipt2, hasManifest);
|
|
51510
|
+
banner("check");
|
|
51511
|
+
if (unknownChannel) {
|
|
51512
|
+
status("unknown (install receipt is unreadable or invalid; installation channel cannot be established)", "warn");
|
|
51513
|
+
if (!doctrine) return;
|
|
51514
|
+
blank();
|
|
51515
|
+
} else if (route !== "marketplace") {
|
|
51516
|
+
const installed = receipt2?.version ?? readInstallManifest(installRoot)?.version ?? "unknown";
|
|
51517
|
+
const freshness = await (options2.resolveFreshness ?? resolveFreshness)({
|
|
51518
|
+
installed,
|
|
51519
|
+
env: process.env,
|
|
51520
|
+
now: Date.now(),
|
|
51521
|
+
cwd: installRoot
|
|
51522
|
+
});
|
|
51523
|
+
const published2 = publishedVersionCheck(freshness, "local");
|
|
51524
|
+
meta3("source", "bundled local package");
|
|
51525
|
+
blank();
|
|
51526
|
+
status(published2.message, published2.status === "pass" ? "ok" : "warn");
|
|
51527
|
+
if (published2.fix !== void 0) line(c.dim(`${where}${published2.fix}`));
|
|
51528
|
+
if (!doctrine) return;
|
|
51529
|
+
blank();
|
|
51530
|
+
}
|
|
51531
|
+
const repo = await resolveMarketplaceRepo2(installRoot);
|
|
51532
|
+
const local = await readLocalConfig(installRoot);
|
|
51533
|
+
meta3("marketplace", repo);
|
|
51534
|
+
blank();
|
|
51535
|
+
const marketplace = remote.fetchRemoteMarketplace(repo);
|
|
51536
|
+
if (!marketplace.ok) {
|
|
51537
|
+
status(`could not fetch remote marketplace: ${marketplace.error}`, "err");
|
|
51538
|
+
line(c.dim("verify `gh auth status` and that you have access to the repo."));
|
|
51539
|
+
process.exit(1);
|
|
51540
|
+
}
|
|
51541
|
+
const drift = route === "marketplace" && !unknownChannel ? reportVersionDrift(local, marketplace.value, repo, remote) : 0;
|
|
51542
|
+
if (doctrine) {
|
|
51543
|
+
blank();
|
|
51544
|
+
await reportDoctrineDrift(installRoot, where, marketplace.value, repo, remote);
|
|
51545
|
+
}
|
|
51546
|
+
if (route !== "marketplace" || unknownChannel) return;
|
|
51547
|
+
if (drift > 0) {
|
|
51548
|
+
footer(
|
|
51549
|
+
`${c.yellow(`${drift} plugin${drift > 1 ? "s" : ""} behind`)} ${glyph.emdash} run ${where}${c.bold(
|
|
51550
|
+
`${PRODUCT_COMMAND} update`
|
|
51551
|
+
)} ${c.dim("(refreshes the plugin cache + bumps the pins this check measures), then restart Claude Code")}`
|
|
51552
|
+
);
|
|
51553
|
+
} else {
|
|
51554
|
+
footer(c.dim("all up to date"));
|
|
51555
|
+
}
|
|
51556
|
+
}
|
|
51557
|
+
async function receiptEvidenceExists(root) {
|
|
51558
|
+
try {
|
|
51559
|
+
await lstat(voidReadPath(root, "receipts", "install-v1.json"));
|
|
51560
|
+
return true;
|
|
51561
|
+
} catch (error62) {
|
|
51562
|
+
return !(error62 instanceof Error && "code" in error62 && error62.code === "ENOENT");
|
|
51563
|
+
}
|
|
51564
|
+
}
|
|
51565
|
+
async function resolveMarketplaceRepo2(installRoot) {
|
|
51566
|
+
const settings = await readSettings(settingsPathFor(installRoot));
|
|
51567
|
+
const entry = settings.extraKnownMarketplaces?.[MARKETPLACE_NAME];
|
|
51568
|
+
if (entry && typeof entry === "object") {
|
|
51569
|
+
const source2 = entry.source;
|
|
51570
|
+
if (source2?.repo) return source2.repo;
|
|
51571
|
+
}
|
|
51572
|
+
return MARKETPLACE_REPO;
|
|
51573
|
+
}
|
|
51574
|
+
async function readLocalConfig(installRoot) {
|
|
51575
|
+
const configPath = join(installRoot, ".void", "config.json");
|
|
51576
|
+
if (!existsSync(configPath)) return {};
|
|
51577
|
+
try {
|
|
51578
|
+
return JSON.parse(await readFile(configPath, "utf8"));
|
|
51579
|
+
} catch {
|
|
51580
|
+
return {};
|
|
51581
|
+
}
|
|
51582
|
+
}
|
|
51583
|
+
function reportVersionDrift(local, marketplace, marketplaceRepo, remote) {
|
|
51584
|
+
const localVersions = {
|
|
51585
|
+
[CORE_PLUGIN_NAME]: local.core
|
|
51586
|
+
};
|
|
51587
|
+
for (const pack2 of PACKS) {
|
|
51588
|
+
localVersions[pack2.name] = local.packs?.[`@voidcorp/${pack2.name}`];
|
|
51589
|
+
}
|
|
51590
|
+
let drift = 0;
|
|
51591
|
+
for (const plugin of marketplace.plugins) {
|
|
51592
|
+
const declaredRaw = localVersions[plugin.name];
|
|
51593
|
+
const localStr = declaredRaw ? normalizeVersion(declaredRaw) : glyph.emdash;
|
|
51594
|
+
const remoteFetch = remote.fetchPinnedPluginVersion(plugin, marketplaceRepo);
|
|
51595
|
+
if (!remoteFetch.ok) {
|
|
51596
|
+
row({ mark: "info", label: plugin.name, versions: [localStr, glyph.emdash], suffix: c.dim(remoteFetch.error) });
|
|
51597
|
+
continue;
|
|
51598
|
+
}
|
|
51599
|
+
const remoteStr = remoteFetch.value;
|
|
51600
|
+
if (!declaredRaw) {
|
|
51601
|
+
row({
|
|
51602
|
+
mark: "info",
|
|
51603
|
+
label: plugin.name,
|
|
51604
|
+
versions: [localStr, remoteStr],
|
|
51605
|
+
suffix: c.dim("not installed")
|
|
51606
|
+
});
|
|
51607
|
+
} else if (compareVersions(localStr, remoteStr) < 0) {
|
|
51608
|
+
drift += 1;
|
|
51609
|
+
row({
|
|
51610
|
+
mark: "warn",
|
|
51611
|
+
label: plugin.name,
|
|
51612
|
+
versions: [localStr, remoteStr],
|
|
51613
|
+
suffix: c.yellow("update available")
|
|
51614
|
+
});
|
|
51615
|
+
} else {
|
|
51616
|
+
row({
|
|
51617
|
+
mark: "ok",
|
|
51618
|
+
label: plugin.name,
|
|
51619
|
+
versions: [localStr, remoteStr],
|
|
51620
|
+
suffix: c.dim("up to date")
|
|
51621
|
+
});
|
|
51622
|
+
}
|
|
51623
|
+
}
|
|
51624
|
+
return drift;
|
|
51625
|
+
}
|
|
51626
|
+
async function reportDoctrineDrift(installRoot, where, marketplace, marketplaceRepo, remote) {
|
|
51627
|
+
const migrated = join(installRoot, ".void", "installed", "PHILOSOPHY.md");
|
|
51628
|
+
const localPath = existsSync(migrated) ? migrated : join(installRoot, ".void", "PHILOSOPHY.md");
|
|
51629
|
+
if (!existsSync(localPath)) {
|
|
51630
|
+
status(`PHILOSOPHY.md missing locally \u2014 run ${where}\`${PRODUCT_COMMAND} init\` to install.`, "warn");
|
|
51631
|
+
return;
|
|
51632
|
+
}
|
|
51633
|
+
const localText = await readFile(localPath, "utf8");
|
|
51634
|
+
const fetched = remote.fetchRemotePhilosophy(marketplace, CORE_PLUGIN_NAME, marketplaceRepo);
|
|
51635
|
+
if (!fetched.ok) {
|
|
51636
|
+
status(`could not fetch remote PHILOSOPHY.md: ${fetched.error}`, "warn");
|
|
51637
|
+
return;
|
|
51638
|
+
}
|
|
51639
|
+
if (normalizeNewlines(localText) === normalizeNewlines(fetched.value)) {
|
|
51640
|
+
status(`PHILOSOPHY.md ${c.dim("in sync")}`);
|
|
51641
|
+
return;
|
|
51642
|
+
}
|
|
51643
|
+
const localLines = localText.split("\n").length;
|
|
51644
|
+
const remoteLines = fetched.value.split("\n").length;
|
|
51645
|
+
status(
|
|
51646
|
+
`PHILOSOPHY.md drift (local ${localLines}L, remote ${remoteLines}L) \u2014 run ${where}\`${PRODUCT_COMMAND} init\` to overwrite`,
|
|
51647
|
+
"warn"
|
|
51648
|
+
);
|
|
51649
|
+
}
|
|
51650
|
+
function normalizeNewlines(s) {
|
|
51651
|
+
return s.replace(/\r\n/g, "\n").trimEnd();
|
|
51652
|
+
}
|
|
51653
|
+
|
|
51518
51654
|
// src/commands/autopilot.ts
|
|
51519
51655
|
init_esm_shims();
|
|
51520
51656
|
|
|
@@ -52489,9 +52625,9 @@ function resultHookWiring(settings) {
|
|
|
52489
52625
|
return document.success ? stopWiring(document.data.hooks) : "missing";
|
|
52490
52626
|
}
|
|
52491
52627
|
function collect(stream2, onLimit) {
|
|
52492
|
-
return new Promise((
|
|
52628
|
+
return new Promise((resolve45) => {
|
|
52493
52629
|
if (stream2 === null) {
|
|
52494
|
-
|
|
52630
|
+
resolve45("");
|
|
52495
52631
|
return;
|
|
52496
52632
|
}
|
|
52497
52633
|
const chunks = [];
|
|
@@ -52504,18 +52640,18 @@ function collect(stream2, onLimit) {
|
|
|
52504
52640
|
else
|
|
52505
52641
|
chunks.push(bytes);
|
|
52506
52642
|
});
|
|
52507
|
-
stream2.once("close", () =>
|
|
52508
|
-
stream2.once("error", () =>
|
|
52643
|
+
stream2.once("close", () => resolve45(Buffer.concat(chunks).toString("utf8")));
|
|
52644
|
+
stream2.once("error", () => resolve45(Buffer.concat(chunks).toString("utf8")));
|
|
52509
52645
|
});
|
|
52510
52646
|
}
|
|
52511
52647
|
function runBounded(config2, args, cwd, timeoutMs) {
|
|
52512
52648
|
const spawn4 = config2.spawn ?? ((executable2, argv, options2) => spawn(executable2, argv, options2));
|
|
52513
|
-
return new Promise((
|
|
52649
|
+
return new Promise((resolve45) => {
|
|
52514
52650
|
let child;
|
|
52515
52651
|
try {
|
|
52516
52652
|
child = spawn4(config2.executable, args, { cwd, env: config2.env, shell: false, stdio: ["ignore", "pipe", "pipe"] });
|
|
52517
52653
|
} catch (error62) {
|
|
52518
|
-
|
|
52654
|
+
resolve45({ kind: "not-started", cause: error62 instanceof Error ? error62.message : String(error62) });
|
|
52519
52655
|
return;
|
|
52520
52656
|
}
|
|
52521
52657
|
let timedOut = false;
|
|
@@ -52530,11 +52666,11 @@ function runBounded(config2, args, cwd, timeoutMs) {
|
|
|
52530
52666
|
const output2 = Promise.all([collect(child.stdout, terminate), collect(child.stderr, terminate)]);
|
|
52531
52667
|
child.once("error", (error62) => {
|
|
52532
52668
|
clearTimeout(timer);
|
|
52533
|
-
|
|
52669
|
+
resolve45({ kind: "not-started", cause: error62 instanceof Error ? error62.message : String(error62) });
|
|
52534
52670
|
});
|
|
52535
52671
|
child.once("close", (code2) => {
|
|
52536
52672
|
clearTimeout(timer);
|
|
52537
|
-
void output2.then(([stdout, stderr]) =>
|
|
52673
|
+
void output2.then(([stdout, stderr]) => resolve45(timedOut ? { kind: "timed-out" } : { kind: "exited", code: typeof code2 === "number" ? code2 : void 0, stdout, stderr }));
|
|
52538
52674
|
});
|
|
52539
52675
|
});
|
|
52540
52676
|
}
|
|
@@ -52950,7 +53086,7 @@ async function socketRefusal(socket) {
|
|
|
52950
53086
|
return void 0;
|
|
52951
53087
|
}
|
|
52952
53088
|
function connect(socket, limits) {
|
|
52953
|
-
return new Promise((
|
|
53089
|
+
return new Promise((resolve45) => {
|
|
52954
53090
|
const ws = new wrapper_default(`ws+unix://${socket}:/`, {
|
|
52955
53091
|
perMessageDeflate: false,
|
|
52956
53092
|
handshakeTimeout: limits.timeouts.callMs,
|
|
@@ -52984,13 +53120,13 @@ function connect(socket, limits) {
|
|
|
52984
53120
|
if (error62.code === "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH") {
|
|
52985
53121
|
closeAll(`a reply of the Codex daemon exceeded the ${String(limits.maxFrameBytes)}-byte frame bound`);
|
|
52986
53122
|
}
|
|
52987
|
-
|
|
53123
|
+
resolve45({
|
|
52988
53124
|
cause: `the Codex daemon does not answer on ${socket}: ${printable2(error62.message, MESSAGE_MAX)}`,
|
|
52989
53125
|
action: DAEMON_START
|
|
52990
53126
|
});
|
|
52991
53127
|
});
|
|
52992
53128
|
ws.on("close", () => closeAll("the connection closed"));
|
|
52993
|
-
ws.once("open", () =>
|
|
53129
|
+
ws.once("open", () => resolve45({
|
|
52994
53130
|
call(method, params, timeoutMs) {
|
|
52995
53131
|
if (closed !== void 0)
|
|
52996
53132
|
return Promise.resolve({ ok: false, kind: "closed", message: closed });
|
|
@@ -58250,13 +58386,13 @@ async function autopilotReview(argv, root) {
|
|
|
58250
58386
|
}
|
|
58251
58387
|
}
|
|
58252
58388
|
function readAllStdin() {
|
|
58253
|
-
return new Promise((
|
|
58389
|
+
return new Promise((resolve45, reject) => {
|
|
58254
58390
|
let data2 = "";
|
|
58255
58391
|
process.stdin.setEncoding("utf8");
|
|
58256
58392
|
process.stdin.on("data", (chunk) => {
|
|
58257
58393
|
data2 += chunk;
|
|
58258
58394
|
});
|
|
58259
|
-
process.stdin.on("end", () =>
|
|
58395
|
+
process.stdin.on("end", () => resolve45(data2));
|
|
58260
58396
|
process.stdin.on("error", reject);
|
|
58261
58397
|
});
|
|
58262
58398
|
}
|
|
@@ -60667,11 +60803,11 @@ function parseUntracked(output2) {
|
|
|
60667
60803
|
function parseGitOwnership(output2, knownPaths) {
|
|
60668
60804
|
const owners = {};
|
|
60669
60805
|
for (const record32 of output2.split("").slice(1)) {
|
|
60670
|
-
const
|
|
60671
|
-
if (
|
|
60672
|
-
const owner = record32.slice(0,
|
|
60806
|
+
const boundary2 = record32.indexOf("");
|
|
60807
|
+
if (boundary2 < 1) continue;
|
|
60808
|
+
const owner = record32.slice(0, boundary2);
|
|
60673
60809
|
if (owner.length > 256 || containsControl2(owner)) continue;
|
|
60674
|
-
const paths = record32.slice(
|
|
60810
|
+
const paths = record32.slice(boundary2 + 1).split("\0");
|
|
60675
60811
|
for (const rawPath of paths) {
|
|
60676
60812
|
const path3 = rawPath.startsWith("\n") ? rawPath.slice(1) : rawPath;
|
|
60677
60813
|
if (path3.length === 0) continue;
|
|
@@ -65993,7 +66129,7 @@ function requestedPort(args) {
|
|
|
65993
66129
|
async function ui(args) {
|
|
65994
66130
|
const launchToken = randomBytes(32).toString("base64url");
|
|
65995
66131
|
banner("ui");
|
|
65996
|
-
await new Promise((
|
|
66132
|
+
await new Promise((resolve45) => {
|
|
65997
66133
|
const server = startCommandCenter({
|
|
65998
66134
|
port: requestedPort(args),
|
|
65999
66135
|
launchToken,
|
|
@@ -66011,7 +66147,7 @@ async function ui(args) {
|
|
|
66011
66147
|
}
|
|
66012
66148
|
});
|
|
66013
66149
|
const stop2 = () => {
|
|
66014
|
-
server.close(() =>
|
|
66150
|
+
server.close(() => resolve45());
|
|
66015
66151
|
};
|
|
66016
66152
|
process.once("SIGINT", stop2);
|
|
66017
66153
|
process.once("SIGTERM", stop2);
|
|
@@ -68908,7 +69044,7 @@ async function recordSpecialistRequests(root, missionId, envelopes, planHash) {
|
|
|
68908
69044
|
init_esm_shims();
|
|
68909
69045
|
|
|
68910
69046
|
// package.json
|
|
68911
|
-
var version2 = "7.0.
|
|
69047
|
+
var version2 = "7.0.2";
|
|
68912
69048
|
|
|
68913
69049
|
// src/lib/runs/verify.ts
|
|
68914
69050
|
var MAX_CAPTURE_BYTES = 64 * 1024;
|