vibe-coding-master 0.6.14 → 0.6.16
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/dist/backend/services/gate-review-service.js +50 -1
- package/dist/backend/templates/harness/claude-root.js +1 -1
- package/dist/backend/templates/harness/gate-review.js +47 -0
- package/dist/backend/templates/harness/project-manager-agent.js +3 -8
- package/dist-frontend/assets/{index-Cf5EOrjk.js → index-C5E5jLp-.js} +49 -49
- package/dist-frontend/assets/index-DmSHDyiQ.css +32 -0
- package/dist-frontend/index.html +2 -2
- package/package.json +1 -1
- package/dist-frontend/assets/index-sTAVWdNl.css +0 -32
|
@@ -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 : "";
|
|
@@ -6,7 +6,7 @@ export function renderRootClaudeHarnessRules() {
|
|
|
6
6
|
- Use \`vcm-route-message\` whenever a VCM role hands off work, asks another role a question, reports a result, reports a blocker, or raises a finding. Follow its write-then-stop rule.
|
|
7
7
|
- Use \`vcm-long-running-validation\` for long-running validation. Follow the background job limits below.
|
|
8
8
|
- Use \`vcm-report-harness-issue\` when you notice a reusable VCM harness problem. Record feedback; do not contact Harness Engineer directly.
|
|
9
|
-
- Project-manager runs \`vcm-gate-review\`
|
|
9
|
+
- Project-manager runs \`vcm-gate-review\` unconditionally at every Gate Review trigger point and on VCM Gate Review callbacks; the tool reports the authoritative enable state.
|
|
10
10
|
|
|
11
11
|
## VCM Harness Scope
|
|
12
12
|
|
|
@@ -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 (
|
|
@@ -84,15 +84,10 @@ PM may lightly rewrite the user's words to:
|
|
|
84
84
|
|
|
85
85
|
### Gate Review Gates
|
|
86
86
|
|
|
87
|
-
- Gate Review
|
|
88
|
-
- Within a confirmed delivery gate, the request is mandatory and unconditional: use the \`vcm-gate-review\` skill to run \`.ai/tools/request-gate-review --gate <gate>\` without judging whether Gate Review is enabled. The tool is the source of truth.
|
|
89
|
-
- Trigger points:
|
|
90
|
-
- \`architecture-plan\`: current \`.ai/vcm/handoffs/architecture-plan.md\` exists and PM is about to dispatch Coder.
|
|
91
|
-
- \`validation-adequacy\`: current \`.ai/vcm/handoffs/review-report.md\` exists and PM is about to start docs sync or final acceptance.
|
|
92
|
-
- \`final-diff\`: current final acceptance evidence exists and PM is about to prepare PR or close the task.
|
|
93
|
-
- Questions, clarifications, role consultations, explanations, status replies, and user-directed role Q&A do not trigger Gate Review.
|
|
87
|
+
- Gate Review requests are mandatory and unconditional. At every trigger point, use the \`vcm-gate-review\` skill to run \`.ai/tools/request-gate-review --gate <gate>\` without first judging whether Gate Review is enabled. The tool (via VCM) is the single source of truth for enable state; never skip the run because you assume Gate Review is off or because the worktree has no gate-review index yet.
|
|
94
88
|
- The tool's first output line decides the next step: \`disabled\`, \`not_required\`, or \`already_approved\` continue the normal VCM flow; \`started\` or \`running\` stop the turn and wait for the VCM callback; \`failed_to_start\` is a hard stop — report it to the user and do not silently proceed past the gate.
|
|
95
|
-
-
|
|
89
|
+
- Trigger points (run each unconditionally): before coder dispatch run \`architecture-plan\`; before docs sync or final acceptance run \`validation-adequacy\`; before PR preparation run \`final-diff\`.
|
|
90
|
+
- On a callback, accept only \`approve\` or \`request_changes\`. On \`request_changes\`, route \`architecture-plan\`/\`final-diff\` reports to architect (Debug Mode or Replan assessment) and \`validation-adequacy\` reports to reviewer.
|
|
96
91
|
- Do not ask Gate Reviewer to choose owners, fixes, Replan, or user-intervention needs.
|
|
97
92
|
- Record gate decision, report path, and any skip or override reason.
|
|
98
93
|
|