vibe-coding-master 0.6.13 → 0.6.15
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.
|
@@ -28,6 +28,10 @@ const SOURCE_ARTIFACTS = {
|
|
|
28
28
|
".ai/vcm/handoffs/final-acceptance.md"
|
|
29
29
|
]
|
|
30
30
|
};
|
|
31
|
+
const CORE_INPUT_ARTIFACTS = {
|
|
32
|
+
"architecture-plan": ".ai/vcm/handoffs/architecture-plan.md",
|
|
33
|
+
"validation-adequacy": ".ai/vcm/handoffs/review-report.md"
|
|
34
|
+
};
|
|
31
35
|
const VALID_SEVERITIES = new Set(["critical", "high", "medium", "low"]);
|
|
32
36
|
export function createGateReviewService(deps) {
|
|
33
37
|
const now = deps.now ?? (() => new Date().toISOString());
|
|
@@ -80,6 +84,30 @@ export function createGateReviewService(deps) {
|
|
|
80
84
|
if (record.status === "running" && !options.force) {
|
|
81
85
|
return { status: "running", gate, record, message: "Gate review is already running." };
|
|
82
86
|
}
|
|
87
|
+
const coreInput = await readCoreInputArtifact(deps.fs, context.taskRepoRoot, gate);
|
|
88
|
+
if (coreInput && coreInput.status !== "ready") {
|
|
89
|
+
index = applyGateState(index, gate, {
|
|
90
|
+
status: "not_required",
|
|
91
|
+
decision: undefined,
|
|
92
|
+
error: undefined,
|
|
93
|
+
exceptionReason: undefined,
|
|
94
|
+
requestId: undefined,
|
|
95
|
+
requestPath: undefined,
|
|
96
|
+
inputHash: undefined,
|
|
97
|
+
requestedAt: undefined,
|
|
98
|
+
startedAt: undefined,
|
|
99
|
+
completedAt: undefined,
|
|
100
|
+
callbackStatus: "not_sent",
|
|
101
|
+
callbackError: undefined
|
|
102
|
+
}, now(), true);
|
|
103
|
+
await saveIndex(deps.fs, context.taskRepoRoot, index);
|
|
104
|
+
return {
|
|
105
|
+
status: "not_required",
|
|
106
|
+
gate,
|
|
107
|
+
record: index.gates[gate],
|
|
108
|
+
message: `${coreInput.path} is ${coreInput.status}.`
|
|
109
|
+
};
|
|
110
|
+
}
|
|
83
111
|
const inputHash = await computeInputHash(deps, context.taskRepoRoot, gate);
|
|
84
112
|
if (!options.force
|
|
85
113
|
&& record.status === "completed"
|
|
@@ -436,7 +464,7 @@ function normalizeIndex(raw, config, timestamp) {
|
|
|
436
464
|
: "disabled";
|
|
437
465
|
const existingStatus = normalizeGateStatus(existing?.status);
|
|
438
466
|
const status = config.enabled && required
|
|
439
|
-
? (existingStatus === "disabled"
|
|
467
|
+
? (existingStatus === "disabled" ? "pending" : existingStatus ?? fallbackStatus)
|
|
440
468
|
: fallbackStatus;
|
|
441
469
|
gates[gate] = {
|
|
442
470
|
gate,
|
|
@@ -495,6 +523,12 @@ async function saveIndex(fs, taskRepoRoot, index) {
|
|
|
495
523
|
}
|
|
496
524
|
async function computeInputHash(deps, taskRepoRoot, gate) {
|
|
497
525
|
const digest = createHash("sha256");
|
|
526
|
+
const coreArtifact = CORE_INPUT_ARTIFACTS[gate];
|
|
527
|
+
if (coreArtifact) {
|
|
528
|
+
digest.update(coreArtifact);
|
|
529
|
+
digest.update(await deps.fs.readText(resolveRepoPath(taskRepoRoot, coreArtifact)));
|
|
530
|
+
return digest.digest("hex");
|
|
531
|
+
}
|
|
498
532
|
const common = [
|
|
499
533
|
"CLAUDE.md",
|
|
500
534
|
".claude/agents/gate-reviewer.md",
|
|
@@ -518,6 +552,21 @@ async function computeInputHash(deps, taskRepoRoot, gate) {
|
|
|
518
552
|
}
|
|
519
553
|
return digest.digest("hex");
|
|
520
554
|
}
|
|
555
|
+
async function readCoreInputArtifact(fs, taskRepoRoot, gate) {
|
|
556
|
+
const relativePath = CORE_INPUT_ARTIFACTS[gate];
|
|
557
|
+
if (!relativePath) {
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
const absolutePath = resolveRepoPath(taskRepoRoot, relativePath);
|
|
561
|
+
if (!await fs.pathExists(absolutePath)) {
|
|
562
|
+
return { path: relativePath, status: "missing" };
|
|
563
|
+
}
|
|
564
|
+
const content = await fs.readText(absolutePath);
|
|
565
|
+
if (content.trim().length === 0) {
|
|
566
|
+
return { path: relativePath, status: "empty" };
|
|
567
|
+
}
|
|
568
|
+
return { path: relativePath, status: "ready" };
|
|
569
|
+
}
|
|
521
570
|
async function commandStdout(runner, cwd, args) {
|
|
522
571
|
const result = await runner.run("git", args, { cwd });
|
|
523
572
|
return result.exitCode === 0 ? result.stdout : "";
|
|
@@ -192,6 +192,10 @@ SOURCE_ARTIFACTS = {
|
|
|
192
192
|
".ai/vcm/handoffs/final-acceptance.md",
|
|
193
193
|
],
|
|
194
194
|
}
|
|
195
|
+
CORE_INPUT_ARTIFACTS = {
|
|
196
|
+
"architecture-plan": ".ai/vcm/handoffs/architecture-plan.md",
|
|
197
|
+
"validation-adequacy": ".ai/vcm/handoffs/review-report.md",
|
|
198
|
+
}
|
|
195
199
|
|
|
196
200
|
|
|
197
201
|
def root_dir() -> Path:
|
|
@@ -282,6 +286,13 @@ def command_output(root: Path, command: list[str]) -> bytes:
|
|
|
282
286
|
|
|
283
287
|
def input_hash(root: Path, gate: str) -> str:
|
|
284
288
|
digest = hashlib.sha256()
|
|
289
|
+
core_artifact = CORE_INPUT_ARTIFACTS.get(gate)
|
|
290
|
+
if core_artifact:
|
|
291
|
+
path = root / core_artifact
|
|
292
|
+
digest.update(core_artifact.encode())
|
|
293
|
+
digest.update(path.read_bytes())
|
|
294
|
+
return digest.hexdigest()
|
|
295
|
+
|
|
285
296
|
common = [
|
|
286
297
|
"CLAUDE.md",
|
|
287
298
|
".claude/agents/gate-reviewer.md",
|
|
@@ -302,6 +313,18 @@ def input_hash(root: Path, gate: str) -> str:
|
|
|
302
313
|
return digest.hexdigest()
|
|
303
314
|
|
|
304
315
|
|
|
316
|
+
def core_input_status(root: Path, gate: str) -> tuple[str, str] | None:
|
|
317
|
+
core_artifact = CORE_INPUT_ARTIFACTS.get(gate)
|
|
318
|
+
if not core_artifact:
|
|
319
|
+
return None
|
|
320
|
+
path = root / core_artifact
|
|
321
|
+
if not path.is_file():
|
|
322
|
+
return (core_artifact, "missing")
|
|
323
|
+
if not path.read_text().strip():
|
|
324
|
+
return (core_artifact, "empty")
|
|
325
|
+
return (core_artifact, "ready")
|
|
326
|
+
|
|
327
|
+
|
|
305
328
|
def request_id(gate: str) -> str:
|
|
306
329
|
stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
|
|
307
330
|
return f"{stamp}-{gate}-{uuid.uuid4().hex[:8]}"
|
|
@@ -340,6 +363,30 @@ def local_request(gate: str) -> int:
|
|
|
340
363
|
print_result("not_required", gate=gate)
|
|
341
364
|
return 0
|
|
342
365
|
|
|
366
|
+
core_status = core_input_status(root, gate)
|
|
367
|
+
if core_status and core_status[1] != "ready":
|
|
368
|
+
gate_record = index["gates"].setdefault(gate, {})
|
|
369
|
+
gate_record.update({
|
|
370
|
+
"status": "not_required",
|
|
371
|
+
"decision": None,
|
|
372
|
+
"error": None,
|
|
373
|
+
"exceptionReason": None,
|
|
374
|
+
"requestId": None,
|
|
375
|
+
"requestPath": None,
|
|
376
|
+
"inputHash": None,
|
|
377
|
+
"requestedAt": None,
|
|
378
|
+
"startedAt": None,
|
|
379
|
+
"completedAt": None,
|
|
380
|
+
"callbackStatus": "not_sent",
|
|
381
|
+
"callbackError": None,
|
|
382
|
+
"updatedAt": now_iso(),
|
|
383
|
+
})
|
|
384
|
+
if index.get("activeGate") == gate:
|
|
385
|
+
index["activeGate"] = None
|
|
386
|
+
write_json(index_path, index)
|
|
387
|
+
print_result("not_required", gate=gate, message=f"{core_status[0]} is {core_status[1]}.")
|
|
388
|
+
return 0
|
|
389
|
+
|
|
343
390
|
current_hash = input_hash(root, gate)
|
|
344
391
|
gate_record = index["gates"].get(gate, {})
|
|
345
392
|
if (
|