vibe-coding-master 0.8.6 → 0.8.7

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/README.md CHANGED
@@ -595,11 +595,17 @@ with the exact assigned `--path` and Assignment ID. Reports are isolated under
595
595
  The reported commit must modify the target document within the assignment's
596
596
  original commit range; unrelated later commits do not invalidate it. Existing
597
597
  correct documentation can be reported as `unchanged` without a new commit.
598
+ For `synced`, the entire `Commit` section is one bare lowercase hexadecimal
599
+ hash (7-40 characters), without Markdown or explanatory text. The template,
600
+ artifact submission, and assignment completion use the same format contract.
598
601
 
599
602
  Assignments run one at a time. A failed assignment does not block later items.
600
603
  After the remaining items finish, unresolved failures are reported in Harness
601
604
  Studio with their causes and individual Retry buttons. Retry preserves earlier
602
605
  committed work and the original baseline, including after a backend restart.
606
+ An old assignment whose baseline was already overwritten is not automatically
607
+ rebased; verify the current document and use `unchanged` when it already preserves
608
+ the assigned content. Errors identify the reported commit and recorded range.
603
609
  Migration content and review snapshots remain in the task-local run directory;
604
610
  failures do not automatically restore removed memory. Turning Auto Memory off
605
611
  does not discard or cancel already-applied document migrations.
@@ -1,6 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import path from "node:path";
3
- import { checkMarkdownArtifact, readArtifactSectionValue } from "../../shared/validation/artifact-check.js";
3
+ import { checkMarkdownArtifact, readArtifactSectionContent, readArtifactSectionValue } from "../../shared/validation/artifact-check.js";
4
+ import { DOCS_UPDATE_COMMIT_RULE } from "../../shared/validation/artifact-contract.js";
4
5
  import { resolveRepoPath } from "../adapters/filesystem.js";
5
6
  import { VcmError } from "../errors.js";
6
7
  import { submitTerminalInput } from "../runtime/terminal-submit.js";
@@ -780,24 +781,34 @@ export function createAutoMemoryService(deps) {
780
781
  return currentHead;
781
782
  }
782
783
  async function validateDurableDocCommit(taskRepoRoot, assignment, reportContent, currentHead) {
783
- if (!assignment.baseCommit || currentHead === assignment.baseCommit) {
784
- throw new Error("documentation changes were not committed");
784
+ const reportedCommit = readArtifactSectionContent(reportContent, "Commit");
785
+ let commit;
786
+ try {
787
+ commit = (await deps.git.getCommitInfo(taskRepoRoot, reportedCommit)).sha;
785
788
  }
786
- const changedPaths = await deps.git.getChangedPaths(taskRepoRoot, assignment.baseCommit, currentHead);
787
- if (!changedPaths.includes(assignment.targetPath)) {
788
- throw new Error(`documentation commit does not include ${assignment.targetPath}`);
789
+ catch (error) {
790
+ const detail = error instanceof VcmError && error.hint ? `${errorMessage(error)} ${error.hint}` : errorMessage(error);
791
+ throw new Error(`Commit ${reportedCommit} could not be resolved to a unique Git commit: ${detail}`);
792
+ }
793
+ const existingContentHint = `If ${assignment.targetPath} already preserves the assigned content, report unchanged with verification evidence; do not create a redundant commit.`;
794
+ if (!assignment.baseCommit) {
795
+ throw new Error(`Assignment ${assignment.id} has no recorded commit baseline; cannot validate Commit ${commit}. ${existingContentHint}`);
796
+ }
797
+ if (currentHead === assignment.baseCommit) {
798
+ throw new Error(`No commits follow assignment baseline ${assignment.baseCommit} (HEAD is the same commit); received Commit ${commit}. The document may already have been committed before this baseline. ${existingContentHint}`);
789
799
  }
790
- const reportedCommit = readArtifactSectionValue(reportContent, "Commit")?.trim();
791
800
  const commits = await deps.git.getCommitList(taskRepoRoot, `${assignment.baseCommit}..${currentHead}`);
792
- const matches = reportedCommit ? commits.filter((commit) => commit.sha.startsWith(reportedCommit)) : [];
793
- if (matches.length !== 1) {
794
- throw new Error(`Commit must uniquely identify a documentation commit in ${assignment.baseCommit}..${currentHead}; received ${reportedCommit || "empty"}`);
801
+ if (!commits.some((candidate) => candidate.sha === commit)) {
802
+ throw new Error(`Commit ${commit} exists but is outside assignment range ${assignment.baseCommit}..${currentHead}. ${existingContentHint}`);
795
803
  }
796
- const commit = matches[0].sha;
797
804
  const commitPaths = await deps.git.getChangedPaths(taskRepoRoot, `${commit}^`, commit);
798
805
  if (!commitPaths.includes(assignment.targetPath)) {
799
806
  throw new Error(`reported commit ${commit} does not modify ${assignment.targetPath}`);
800
807
  }
808
+ const changedPaths = await deps.git.getChangedPaths(taskRepoRoot, assignment.baseCommit, currentHead);
809
+ if (!changedPaths.includes(assignment.targetPath)) {
810
+ throw new Error(`Commit ${commit} modified ${assignment.targetPath}, but no net change remains in ${assignment.baseCommit}..${currentHead}. Verify the current document before reporting completion.`);
811
+ }
801
812
  return commit;
802
813
  }
803
814
  async function hashOptionalFile(taskRepoRoot, relativePath) {
@@ -1498,6 +1509,7 @@ function buildDurableDocAssignmentPrompt(taskRepoRoot, assignment) {
1498
1509
  `Assigned report path: ${assignment.reportPath}`,
1499
1510
  `Submit with .ai/tools/vcm-artifact docs-update-report --file <candidate> --path ${assignment.reportPath} --mode final`,
1500
1511
  "Set Assignment ID to the exact ID above.",
1512
+ DOCS_UPDATE_COMMIT_RULE,
1501
1513
  "For synced, record the commit that changed the target document; it need not be HEAD. If the document already preserves the content, use unchanged with evidence; do not create a redundant commit.",
1502
1514
  ...(assignment.error ? [`Previous failure: ${assignment.error}`] : []),
1503
1515
  "End the turn after VCM accepts the report."
@@ -1,4 +1,4 @@
1
- import { ARCHITECT_DEBUG_DISPOSITIONS, ARCHITECT_DEBUG_STATUSES, ARCHITECTURE_BRIEF_STATUSES, ARCHITECTURE_DIAGNOSIS_DISPOSITIONS, ARCHITECTURE_EVIDENCE_STATUSES, ARCHITECTURE_PLAN_RESULTS, CODER_COMPLETION_DECISIONS, DOCS_REPORT_DECISIONS, DOCS_SYNC_CORRECTION_OWNERS, FINAL_ACCEPTANCE_DECISIONS, L3_ACTIONS, L3_REQUIRED_VALUES, PLANNING_PROGRESS_STATUSES, STRICT_NONE_VALUE, TEST_INFRASTRUCTURE_STATUSES, TEST_RESULTS, renderArtifactOptions } from "../../shared/validation/artifact-contract.js";
1
+ import { ARCHITECT_DEBUG_DISPOSITIONS, ARCHITECT_DEBUG_STATUSES, ARCHITECTURE_BRIEF_STATUSES, ARCHITECTURE_DIAGNOSIS_DISPOSITIONS, ARCHITECTURE_EVIDENCE_STATUSES, ARCHITECTURE_PLAN_RESULTS, CODER_COMPLETION_DECISIONS, DOCS_REPORT_DECISIONS, DOCS_UPDATE_COMMIT_RULE, DOCS_SYNC_CORRECTION_OWNERS, FINAL_ACCEPTANCE_DECISIONS, L3_ACTIONS, L3_REQUIRED_VALUES, PLANNING_PROGRESS_STATUSES, STRICT_NONE_VALUE, TEST_INFRASTRUCTURE_STATUSES, TEST_RESULTS, renderArtifactOptions } from "../../shared/validation/artifact-contract.js";
2
2
  const CURRENT_HANDOFF_NOTICE = "<!-- VCM current handoff: replace this file with one complete, self-contained snapshot of the current result. Restate all still-relevant evidence; do not refer to a prior revision, route message, Session, or transcript as evidence. -->";
3
3
  export function renderArchitectureBriefTemplate(taskSlug) {
4
4
  return `# Architecture Brief: ${taskSlug}
@@ -534,6 +534,8 @@ export function renderDocsUpdateReportTemplate(taskSlug, assignmentId = "docs-on
534
534
 
535
535
  ${CURRENT_HANDOFF_NOTICE}
536
536
 
537
+ ${DOCS_UPDATE_COMMIT_RULE}
538
+
537
539
  ## Summary
538
540
 
539
541
  TBD
@@ -1,4 +1,4 @@
1
- import { ARCHITECT_DEBUG_DISPOSITIONS, ARCHITECT_DEBUG_STATUSES, ARCHITECTURE_BRIEF_STATUSES, ARCHITECTURE_DIAGNOSIS_DISPOSITIONS, ARCHITECTURE_EVIDENCE_STATUSES, ARCHITECTURE_PLAN_RESULTS, CODER_COMPLETION_DECISIONS, DOCS_REPORT_DECISIONS, DOCS_SYNC_CORRECTION_OWNERS, FINAL_ACCEPTANCE_DECISIONS, L3_ACTIONS, L3_REQUIRED_VALUES, PLANNING_PROGRESS_STATUSES, STRICT_NONE_VALUE, TEST_INFRASTRUCTURE_STATUSES, TEST_RESULTS } from "./artifact-contract.js";
1
+ import { ARCHITECT_DEBUG_DISPOSITIONS, ARCHITECT_DEBUG_STATUSES, ARCHITECTURE_BRIEF_STATUSES, ARCHITECTURE_DIAGNOSIS_DISPOSITIONS, ARCHITECTURE_EVIDENCE_STATUSES, ARCHITECTURE_PLAN_RESULTS, CODER_COMPLETION_DECISIONS, DOCS_REPORT_DECISIONS, DOCS_UPDATE_COMMIT_PATTERN, DOCS_UPDATE_COMMIT_RULE, DOCS_SYNC_CORRECTION_OWNERS, FINAL_ACCEPTANCE_DECISIONS, L3_ACTIONS, L3_REQUIRED_VALUES, PLANNING_PROGRESS_STATUSES, STRICT_NONE_VALUE, TEST_INFRASTRUCTURE_STATUSES, TEST_RESULTS } from "./artifact-contract.js";
2
2
  import { getArtifactDefinition } from "./artifact-registry.js";
3
3
  const PLACEHOLDER_PATTERN = /(^|\n)\s*(TBD|Not run yet\.?|status:\s*draft)\s*(\n|$)/i;
4
4
  export function checkMarkdownArtifact(kind, artifactPath, content, options = {}) {
@@ -252,7 +252,13 @@ function validateArtifactFields(kind, content, mode) {
252
252
  return invalidFields;
253
253
  }
254
254
  if (kind === "docs-update-report") {
255
- return validateDecision(content, DOCS_REPORT_DECISIONS);
255
+ const invalidFields = validateDecision(content, DOCS_REPORT_DECISIONS);
256
+ const decision = readArtifactSectionContent(content, "Decision")?.trim().toLowerCase();
257
+ const commit = readArtifactSectionContent(content, "Commit");
258
+ if (mode === "final" && decision === "synced" && !DOCS_UPDATE_COMMIT_PATTERN.test(commit ?? "")) {
259
+ invalidFields.push(`${DOCS_UPDATE_COMMIT_RULE} Received Commit: ${JSON.stringify(commit ?? "")}.`);
260
+ }
261
+ return invalidFields;
256
262
  }
257
263
  if (kind === "docs-sync-report") {
258
264
  const invalidFields = validateDecision(content, DOCS_REPORT_DECISIONS);
@@ -30,6 +30,8 @@ export const TEST_INFRASTRUCTURE_STATUSES = [
30
30
  export const L3_REQUIRED_VALUES = ["yes", "no"];
31
31
  export const L3_ACTIONS = ["run-existing", "updated", "added"];
32
32
  export const DOCS_REPORT_DECISIONS = ["synced", "unchanged", "blocked"];
33
+ export const DOCS_UPDATE_COMMIT_PATTERN = /^[0-9a-f]{7,40}$/;
34
+ export const DOCS_UPDATE_COMMIT_RULE = "When Decision is synced, Commit must contain only one bare lowercase hexadecimal commit hash (7-40 characters, for example abc1234) on a single line. No backticks, bullets, links, subjects, or extra lines; put explanations in Evidence Reviewed. An unchanged result does not require a new commit.";
33
35
  export const DOCS_SYNC_CORRECTION_OWNERS = ["none", "architect", "coder", "tester"];
34
36
  export const FINAL_ACCEPTANCE_DECISIONS = [
35
37
  "accepted",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-coding-master",
3
- "version": "0.8.6",
3
+ "version": "0.8.7",
4
4
  "description": "Local GUI session cockpit for Claude Code role sessions.",
5
5
  "type": "module",
6
6
  "files": [