vibe-coding-master 0.6.14 → 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" || existingStatus === "not_required" ? "pending" : existingStatus ?? fallbackStatus)
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\` only at formal delivery Gate Review trigger points: the required handoff artifact exists and PM is about to advance across that delivery boundary. Within such a gate, the request is unconditional and the tool reports the authoritative enable state.
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 is artifact-gated and transition-gated. Request it only when the current formal handoff artifact exists and PM is about to advance across that delivery boundary.
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
- - On a callback, accept only \`approve\` or \`request_changes\`. On \`request_changes\`, route \`architecture-plan\`/\`final-diff\` reports to architect and \`validation-adequacy\` reports to reviewer.
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-coding-master",
3
- "version": "0.6.14",
3
+ "version": "0.6.15",
4
4
  "description": "Local GUI session cockpit for Claude Code role sessions.",
5
5
  "type": "module",
6
6
  "files": [