vibe-coding-master 0.7.0 → 0.7.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/README.md +12 -10
- package/dist/backend/api/harness-routes.js +10 -4
- package/dist/backend/cli/install-vcm-harness.js +8 -0
- package/dist/backend/services/auto-memory-service.js +57 -50
- package/dist/backend/services/harness-service.js +9 -0
- package/dist/backend/services/runtime-coordinator-service.js +8 -9
- package/dist/backend/templates/harness/architect-agent.js +1 -1
- package/dist/backend/templates/harness/claude-root.js +2 -0
- package/dist/backend/templates/harness/coder-agent.js +1 -1
- package/dist/backend/templates/harness/coder-worker-agent.js +1 -1
- package/dist/backend/templates/harness/harness-engineer-agent.js +15 -17
- package/dist/backend/templates/harness/project-coding-standards.js +1 -1
- package/dist/backend/templates/harness/project-manager-agent.js +13 -8
- package/dist/backend/templates/harness/role-memory.js +11 -1
- package/dist/backend/templates/harness/tester-agent.js +2 -2
- package/dist/backend/templates/harness/vcm-final-acceptance-skill.js +5 -5
- package/dist/backend/templates/harness/vcm-harness-bootstrap-skill.js +1 -1
- package/dist/backend/templates/harness/vcm-propose-memory-skill.js +35 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -390,11 +390,11 @@ VCM runs it from the active task worktree.
|
|
|
390
390
|
|
|
391
391
|
### Auto Memory
|
|
392
392
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
the result.
|
|
393
|
+
`Auto memory` is the switch for the entire automated memory workflow. During
|
|
394
|
+
Review Task Harness after Final Acceptance, Project Manager, Architect, Coder,
|
|
395
|
+
Tester, and an enabled Gate Reviewer submit proposals in sequence through
|
|
396
|
+
`vcm-propose-memory`. Harness Engineer verifies and consolidates them before VCM
|
|
397
|
+
applies the result. Roles cannot edit active memory directly.
|
|
398
398
|
|
|
399
399
|
Canonical memory is stored under the base repository's `.ai/vcm/memory/`.
|
|
400
400
|
Harness Studio shows current memory and task-local applied history. Memory is
|
|
@@ -405,14 +405,16 @@ Post-task processing is ordered by the backend:
|
|
|
405
405
|
|
|
406
406
|
```text
|
|
407
407
|
Final Acceptance
|
|
408
|
-
->
|
|
408
|
+
-> Review Task Harness
|
|
409
|
+
-> Memory proposals and Harness Engineer review, when Auto Memory is enabled
|
|
409
410
|
-> Task Harness Retrospective
|
|
410
411
|
```
|
|
411
412
|
|
|
412
|
-
Auto Memory
|
|
413
|
-
enabled, both automatic and manual
|
|
414
|
-
|
|
415
|
-
retried from Harness Studio before retrospective
|
|
413
|
+
When Auto Memory is disabled, Review Task Harness does not collect proposals or
|
|
414
|
+
ask Harness Engineer to update memory. When enabled, both automatic and manual
|
|
415
|
+
review requests complete the memory phase before retrospective analysis. A
|
|
416
|
+
failed memory review must be retried from Harness Studio before retrospective
|
|
417
|
+
can continue.
|
|
416
418
|
|
|
417
419
|
## Closing a Task
|
|
418
420
|
|
|
@@ -154,15 +154,21 @@ export function registerHarnessRoutes(app, deps) {
|
|
|
154
154
|
});
|
|
155
155
|
app.post("/api/projects/harness/task-retrospective", async (request) => {
|
|
156
156
|
const { project, task } = await requireHarnessTaskContext(deps, request.body?.taskSlug);
|
|
157
|
-
|
|
157
|
+
const trigger = request.body?.trigger === "auto" ? "auto" : "manual";
|
|
158
|
+
const memoryInput = {
|
|
158
159
|
baseRepoRoot: project.repoRoot,
|
|
159
160
|
taskRepoRoot: task.worktreePath,
|
|
160
161
|
taskSlug: task.taskSlug,
|
|
161
162
|
handoffDir: task.handoffDir,
|
|
162
|
-
roundReady: true
|
|
163
|
-
|
|
163
|
+
roundReady: true,
|
|
164
|
+
requestTrigger: trigger
|
|
165
|
+
};
|
|
166
|
+
await deps.autoMemoryService.reconcileTask(memoryInput);
|
|
167
|
+
const memoryReadiness = await deps.autoMemoryService.getTaskRetrospectiveReadiness(memoryInput);
|
|
168
|
+
if (!memoryReadiness.ready) {
|
|
169
|
+
return deps.harnessFeedbackService.getState(project.repoRoot, task.taskSlug);
|
|
170
|
+
}
|
|
164
171
|
await deps.autoMemoryService.assertHarnessEngineerAvailable(task.worktreePath);
|
|
165
|
-
const trigger = request.body?.trigger === "auto" ? "auto" : "manual";
|
|
166
172
|
return deps.harnessFeedbackService.startTaskRetrospective(project.repoRoot, {
|
|
167
173
|
taskSlug: task.taskSlug,
|
|
168
174
|
taskRepoRoot: task.worktreePath,
|
|
@@ -20,6 +20,7 @@ import { renderTesterHarnessRules } from "../templates/harness/tester-agent.js";
|
|
|
20
20
|
import { renderVcmFinalAcceptanceSkillRules } from "../templates/harness/vcm-final-acceptance-skill.js";
|
|
21
21
|
import { renderVcmHarnessBootstrapSkillRules } from "../templates/harness/vcm-harness-bootstrap-skill.js";
|
|
22
22
|
import { renderVcmLongRunningValidationSkillRules } from "../templates/harness/vcm-long-running-validation-skill.js";
|
|
23
|
+
import { renderVcmProposeMemorySkillRules } from "../templates/harness/vcm-propose-memory-skill.js";
|
|
23
24
|
import { renderVcmReportHarnessIssueSkillRules } from "../templates/harness/vcm-report-harness-issue-skill.js";
|
|
24
25
|
import { renderVcmRouteMessageSkillRules } from "../templates/harness/vcm-route-message-skill.js";
|
|
25
26
|
import { readVcmPackageVersion } from "../app-version.js";
|
|
@@ -248,6 +249,12 @@ const WHOLE_FILES = [
|
|
|
248
249
|
mode: 0o644,
|
|
249
250
|
content: renderSkillFile("VCM Report Harness Issue Skill", "vcm-report-harness-issue", "Use when a VCM role notices a reusable harness problem and needs to record feedback for Harness Engineer review.", renderVcmReportHarnessIssueSkillRules())
|
|
250
251
|
},
|
|
252
|
+
{
|
|
253
|
+
path: ".claude/skills/vcm-propose-memory/SKILL.md",
|
|
254
|
+
category: "skill",
|
|
255
|
+
mode: 0o644,
|
|
256
|
+
content: renderSkillFile("VCM Propose Memory Skill", "vcm-propose-memory", "Use only when VCM requests a role memory proposal during Task Harness Review.", renderVcmProposeMemorySkillRules())
|
|
257
|
+
},
|
|
251
258
|
{
|
|
252
259
|
path: ".ai/tools/request-gate-review",
|
|
253
260
|
category: "runtime-tool",
|
|
@@ -476,6 +483,7 @@ function fixedDirectories() {
|
|
|
476
483
|
".claude/skills/vcm-route-message/",
|
|
477
484
|
".claude/skills/vcm-gate-review/",
|
|
478
485
|
".claude/skills/vcm-report-harness-issue/",
|
|
486
|
+
".claude/skills/vcm-propose-memory/",
|
|
479
487
|
".ai/vcm/translations/",
|
|
480
488
|
".ai/vcm/gate-reviews/",
|
|
481
489
|
".ai/tools/",
|
|
@@ -62,11 +62,16 @@ export function createAutoMemoryService(deps) {
|
|
|
62
62
|
}
|
|
63
63
|
async function getState(baseRepoRoot, taskRepoRoot) {
|
|
64
64
|
await ensureTaskMemorySnapshot(deps.fs, baseRepoRoot, taskRepoRoot);
|
|
65
|
-
|
|
65
|
+
let [active, runs, files] = await Promise.all([
|
|
66
66
|
loadActiveState(taskRepoRoot),
|
|
67
67
|
listRuns(taskRepoRoot),
|
|
68
68
|
listMemoryFiles(taskRepoRoot)
|
|
69
69
|
]);
|
|
70
|
+
if (active && !(await deps.appSettings.getPreferences()).autoMemoryEnabled) {
|
|
71
|
+
await discardActiveReview(taskRepoRoot, active);
|
|
72
|
+
active = undefined;
|
|
73
|
+
runs = await listRuns(taskRepoRoot);
|
|
74
|
+
}
|
|
70
75
|
return {
|
|
71
76
|
version: 1,
|
|
72
77
|
status: active?.status ?? "idle",
|
|
@@ -79,6 +84,13 @@ export function createAutoMemoryService(deps) {
|
|
|
79
84
|
async function reconcileTask(input) {
|
|
80
85
|
await ensureTaskMemorySnapshot(deps.fs, input.baseRepoRoot, input.taskRepoRoot);
|
|
81
86
|
const active = await loadActiveState(input.taskRepoRoot);
|
|
87
|
+
const preferences = await deps.appSettings.getPreferences();
|
|
88
|
+
if (!preferences.autoMemoryEnabled) {
|
|
89
|
+
if (active) {
|
|
90
|
+
await discardActiveReview(input.taskRepoRoot, active);
|
|
91
|
+
}
|
|
92
|
+
return getState(input.baseRepoRoot, input.taskRepoRoot);
|
|
93
|
+
}
|
|
82
94
|
if (active?.status === "collecting") {
|
|
83
95
|
await dispatchCurrentDraft(input.baseRepoRoot, input.taskRepoRoot, active);
|
|
84
96
|
return getState(input.baseRepoRoot, input.taskRepoRoot);
|
|
@@ -87,11 +99,7 @@ export function createAutoMemoryService(deps) {
|
|
|
87
99
|
await dispatchHarnessReview(input.baseRepoRoot, input.taskRepoRoot, active);
|
|
88
100
|
return getState(input.baseRepoRoot, input.taskRepoRoot);
|
|
89
101
|
}
|
|
90
|
-
if (active || !input.roundReady) {
|
|
91
|
-
return getState(input.baseRepoRoot, input.taskRepoRoot);
|
|
92
|
-
}
|
|
93
|
-
const preferences = await deps.appSettings.getPreferences();
|
|
94
|
-
if (!preferences.autoMemoryEnabled) {
|
|
102
|
+
if (active || !input.roundReady || !input.requestTrigger) {
|
|
95
103
|
return getState(input.baseRepoRoot, input.taskRepoRoot);
|
|
96
104
|
}
|
|
97
105
|
if (deps.isHarnessEngineerAvailable && !(await deps.isHarnessEngineerAvailable(input.baseRepoRoot))) {
|
|
@@ -122,6 +130,7 @@ export function createAutoMemoryService(deps) {
|
|
|
122
130
|
taskSlug: input.taskSlug,
|
|
123
131
|
status: "collecting",
|
|
124
132
|
finalAcceptanceHash,
|
|
133
|
+
trigger: input.requestTrigger,
|
|
125
134
|
createdAt: timestamp,
|
|
126
135
|
updatedAt: timestamp,
|
|
127
136
|
drafts
|
|
@@ -138,6 +147,7 @@ export function createAutoMemoryService(deps) {
|
|
|
138
147
|
createdAt: timestamp,
|
|
139
148
|
updatedAt: timestamp,
|
|
140
149
|
finalAcceptanceHash,
|
|
150
|
+
trigger: input.requestTrigger,
|
|
141
151
|
beforeHashes: hashMemorySet(before)
|
|
142
152
|
});
|
|
143
153
|
await persistActiveState(input.taskRepoRoot, state);
|
|
@@ -159,13 +169,15 @@ export function createAutoMemoryService(deps) {
|
|
|
159
169
|
return {
|
|
160
170
|
ready: false,
|
|
161
171
|
disposition,
|
|
172
|
+
trigger: active.trigger,
|
|
162
173
|
reason: disposition === "failed"
|
|
163
174
|
? "Auto Memory failed for this task. Retry it before Task Harness Retrospective."
|
|
164
175
|
: `Auto Memory is ${disposition} for this task.`
|
|
165
176
|
};
|
|
166
177
|
}
|
|
167
|
-
|
|
168
|
-
|
|
178
|
+
const completedRun = await findCompletedRunForFinalAcceptance(input.taskRepoRoot, finalAcceptanceHash);
|
|
179
|
+
if (completedRun) {
|
|
180
|
+
return { ready: true, disposition: "completed", trigger: completedRun.trigger };
|
|
169
181
|
}
|
|
170
182
|
return {
|
|
171
183
|
ready: false,
|
|
@@ -173,18 +185,6 @@ export function createAutoMemoryService(deps) {
|
|
|
173
185
|
reason: "Auto Memory must complete for this Final Acceptance before Task Harness Retrospective."
|
|
174
186
|
};
|
|
175
187
|
}
|
|
176
|
-
async function assertTaskRetrospectiveReady(input) {
|
|
177
|
-
const readiness = await getTaskRetrospectiveReadiness(input);
|
|
178
|
-
if (readiness.ready) {
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
throw new VcmError({
|
|
182
|
-
code: "TASK_MEMORY_REVIEW_NOT_READY",
|
|
183
|
-
message: "Task Harness Retrospective must run after Auto Memory.",
|
|
184
|
-
statusCode: 409,
|
|
185
|
-
hint: readiness.reason
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
188
|
async function isRoleMemoryTurn(taskRepoRoot, role) {
|
|
189
189
|
const state = await loadActiveState(taskRepoRoot);
|
|
190
190
|
const draft = state?.status === "collecting" ? currentDraft(state) : undefined;
|
|
@@ -192,6 +192,13 @@ export function createAutoMemoryService(deps) {
|
|
|
192
192
|
}
|
|
193
193
|
async function handleRoleHook(input) {
|
|
194
194
|
const state = await loadActiveState(input.taskRepoRoot);
|
|
195
|
+
if (!(await deps.appSettings.getPreferences()).autoMemoryEnabled) {
|
|
196
|
+
if (state) {
|
|
197
|
+
await discardActiveReview(input.taskRepoRoot, state);
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
195
202
|
const draft = state?.status === "collecting" ? currentDraft(state) : undefined;
|
|
196
203
|
if (!state || !draft || draft.role !== input.role) {
|
|
197
204
|
return false;
|
|
@@ -237,13 +244,17 @@ export function createAutoMemoryService(deps) {
|
|
|
237
244
|
}
|
|
238
245
|
async function handleHarnessEngineerHook(input) {
|
|
239
246
|
const state = await loadActiveState(input.taskRepoRoot);
|
|
247
|
+
if (!(await deps.appSettings.getPreferences()).autoMemoryEnabled) {
|
|
248
|
+
if (state) {
|
|
249
|
+
await discardActiveReview(input.taskRepoRoot, state);
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
240
254
|
if (state?.status === "reviewing" && !state.reviewPromptDispatchedAt) {
|
|
241
255
|
return false;
|
|
242
256
|
}
|
|
243
257
|
if (!state || state.status !== "reviewing") {
|
|
244
|
-
if (input.eventName === "Stop") {
|
|
245
|
-
await captureHarnessEngineerChanges(input.baseRepoRoot, input.taskRepoRoot, input.taskSlug);
|
|
246
|
-
}
|
|
247
258
|
return false;
|
|
248
259
|
}
|
|
249
260
|
if (input.eventName === "UserPromptSubmit" || input.eventName === "PostCompact") {
|
|
@@ -329,6 +340,10 @@ export function createAutoMemoryService(deps) {
|
|
|
329
340
|
}
|
|
330
341
|
async function assertHarnessEngineerAvailable(taskRepoRoot) {
|
|
331
342
|
const state = await loadActiveState(taskRepoRoot);
|
|
343
|
+
if (state && !(await deps.appSettings.getPreferences()).autoMemoryEnabled) {
|
|
344
|
+
await discardActiveReview(taskRepoRoot, state);
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
332
347
|
if (!state || state.status === "failed") {
|
|
333
348
|
return;
|
|
334
349
|
}
|
|
@@ -341,6 +356,10 @@ export function createAutoMemoryService(deps) {
|
|
|
341
356
|
}
|
|
342
357
|
async function assertNoActiveReview(taskRepoRoot) {
|
|
343
358
|
const state = await loadActiveState(taskRepoRoot);
|
|
359
|
+
if (state && !(await deps.appSettings.getPreferences()).autoMemoryEnabled) {
|
|
360
|
+
await discardActiveReview(taskRepoRoot, state);
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
344
363
|
if (!state) {
|
|
345
364
|
return;
|
|
346
365
|
}
|
|
@@ -437,17 +456,6 @@ export function createAutoMemoryService(deps) {
|
|
|
437
456
|
await failReview(taskRepoRoot, state, `Harness Engineer memory result could not be applied: ${errorMessage(error)}`);
|
|
438
457
|
}
|
|
439
458
|
}
|
|
440
|
-
async function captureHarnessEngineerChanges(baseRepoRoot, taskRepoRoot, taskSlug) {
|
|
441
|
-
await ensureTaskMemorySnapshot(deps.fs, baseRepoRoot, taskRepoRoot);
|
|
442
|
-
const [before, after] = await Promise.all([
|
|
443
|
-
readMemorySet(baseRepoRoot),
|
|
444
|
-
readMemorySet(taskRepoRoot)
|
|
445
|
-
]);
|
|
446
|
-
if (sameHashes(hashMemorySet(before), hashMemorySet(after))) {
|
|
447
|
-
return;
|
|
448
|
-
}
|
|
449
|
-
await createAppliedRun(baseRepoRoot, taskRepoRoot, taskSlug, "harness-engineer", before, after);
|
|
450
|
-
}
|
|
451
459
|
async function createAppliedRun(baseRepoRoot, taskRepoRoot, taskSlug, source, before, after) {
|
|
452
460
|
assertCompleteMemorySet(after);
|
|
453
461
|
const timestamp = now();
|
|
@@ -513,6 +521,7 @@ export function createAutoMemoryService(deps) {
|
|
|
513
521
|
failedAt: run.failedAt,
|
|
514
522
|
revertedAt: run.revertedAt,
|
|
515
523
|
finalAcceptanceHash: run.finalAcceptanceHash,
|
|
524
|
+
trigger: run.trigger,
|
|
516
525
|
diff: run.diff ?? "",
|
|
517
526
|
canRevert: run.status === "applied" && !run.revertedAt && Boolean(run.afterHashes),
|
|
518
527
|
error: run.error
|
|
@@ -534,8 +543,11 @@ export function createAutoMemoryService(deps) {
|
|
|
534
543
|
return files;
|
|
535
544
|
}
|
|
536
545
|
async function hasCompletedRunForFinalAcceptance(taskRepoRoot, finalAcceptanceHash) {
|
|
546
|
+
return Boolean(await findCompletedRunForFinalAcceptance(taskRepoRoot, finalAcceptanceHash));
|
|
547
|
+
}
|
|
548
|
+
async function findCompletedRunForFinalAcceptance(taskRepoRoot, finalAcceptanceHash) {
|
|
537
549
|
const runs = await listRuns(taskRepoRoot);
|
|
538
|
-
return runs.
|
|
550
|
+
return runs.find((run) => run.finalAcceptanceHash === finalAcceptanceHash && (run.status === "applied" || run.status === "reverted"));
|
|
539
551
|
}
|
|
540
552
|
async function loadActiveState(taskRepoRoot) {
|
|
541
553
|
const statePath = resolveRepoPath(taskRepoRoot, MEMORY_REVIEW_STATE_PATH);
|
|
@@ -551,6 +563,10 @@ export function createAutoMemoryService(deps) {
|
|
|
551
563
|
async function clearActiveState(taskRepoRoot) {
|
|
552
564
|
await deps.fs.removePath?.(resolveRepoPath(taskRepoRoot, MEMORY_REVIEW_STATE_PATH), { force: true });
|
|
553
565
|
}
|
|
566
|
+
async function discardActiveReview(taskRepoRoot, state) {
|
|
567
|
+
await clearActiveState(taskRepoRoot);
|
|
568
|
+
await deps.fs.removePath?.(resolveRepoPath(taskRepoRoot, `${MEMORY_REVIEW_RUNS_ROOT}/${state.runId}`), { recursive: true, force: true });
|
|
569
|
+
}
|
|
554
570
|
async function readRun(taskRepoRoot, runId) {
|
|
555
571
|
const runPath = resolveRepoPath(taskRepoRoot, `${MEMORY_REVIEW_RUNS_ROOT}/${requireSafeRunId(runId)}/run.json`);
|
|
556
572
|
if (!(await deps.fs.pathExists(runPath))) {
|
|
@@ -590,7 +606,6 @@ export function createAutoMemoryService(deps) {
|
|
|
590
606
|
reconcileTask,
|
|
591
607
|
getState,
|
|
592
608
|
getTaskRetrospectiveReadiness,
|
|
593
|
-
assertTaskRetrospectiveReady,
|
|
594
609
|
getFile,
|
|
595
610
|
updateFile,
|
|
596
611
|
revertRun,
|
|
@@ -629,44 +644,36 @@ function toActiveReview(state) {
|
|
|
629
644
|
updatedAt: state.updatedAt,
|
|
630
645
|
currentRole: state.status === "collecting" ? currentDraft(state)?.role : undefined,
|
|
631
646
|
drafts: state.drafts,
|
|
647
|
+
trigger: state.trigger,
|
|
632
648
|
error: state.error
|
|
633
649
|
};
|
|
634
650
|
}
|
|
635
651
|
function buildRoleDraftPrompt(taskRepoRoot, state, draft) {
|
|
636
652
|
return [
|
|
637
|
-
"[VCM
|
|
653
|
+
"[VCM Task Harness Review: Memory Proposal]",
|
|
638
654
|
"",
|
|
639
|
-
"
|
|
655
|
+
"Use the vcm-propose-memory skill to submit the assigned proposal.",
|
|
640
656
|
`Task worktree: ${taskRepoRoot}`,
|
|
641
657
|
`Current shared memory: ${resolveRepoPath(taskRepoRoot, `${MEMORY_ROOT}/shared.md`)}`,
|
|
642
658
|
`Current role memory: ${resolveRepoPath(taskRepoRoot, `${MEMORY_ROOT}/roles/${draft.role}.md`)}`,
|
|
643
659
|
`Write the draft to: ${resolveRepoPath(taskRepoRoot, draft.path)}`,
|
|
644
660
|
"",
|
|
645
|
-
"Use this structure:",
|
|
646
|
-
"# Memory Draft",
|
|
647
|
-
"Decision: update | no-change",
|
|
648
|
-
"## Add",
|
|
649
|
-
"## Update",
|
|
650
|
-
"## Remove",
|
|
651
|
-
"## Evidence",
|
|
652
|
-
"",
|
|
653
|
-
"Do not edit memory files, route messages, or handoff artifacts. Do not record task narrative, temporary state, unverified conclusions, or rules that belong in the harness.",
|
|
654
661
|
"End the turn after writing the draft."
|
|
655
662
|
].join("\n");
|
|
656
663
|
}
|
|
657
664
|
function buildHarnessReviewPrompt(taskRepoRoot, state) {
|
|
658
665
|
const runRoot = resolveRepoPath(taskRepoRoot, `${MEMORY_REVIEW_RUNS_ROOT}/${state.runId}`);
|
|
659
666
|
return [
|
|
660
|
-
"[VCM
|
|
667
|
+
"[VCM Task Harness Review: Memory Review]",
|
|
661
668
|
"",
|
|
662
|
-
"Review the role
|
|
669
|
+
"Auto Memory is enabled. Review the role proposals and task evidence, then produce the complete next memory set.",
|
|
663
670
|
`Task worktree: ${taskRepoRoot}`,
|
|
664
671
|
`Role drafts: ${path.join(runRoot, "drafts")}`,
|
|
665
672
|
`Current memory snapshot: ${path.join(runRoot, "before")}`,
|
|
666
673
|
`Write the complete reviewed memory set to: ${path.join(runRoot, "after")}`,
|
|
667
674
|
"",
|
|
668
675
|
"Keep only verified, durable, reusable project knowledge. Merge duplicates, remove stale entries, and keep role-specific knowledge in the matching role file.",
|
|
669
|
-
"
|
|
676
|
+
"Do not record task narrative, temporary state, unverified conclusions, or Harness rules.",
|
|
670
677
|
"Do not edit product code, harness files, the canonical base-repository memory, or review metadata.",
|
|
671
678
|
"All existing files already exist in the after directory. Edit those files in place and end the turn when review is complete."
|
|
672
679
|
].join("\n");
|
|
@@ -17,6 +17,7 @@ import { renderTesterHarnessRules } from "../templates/harness/tester-agent.js";
|
|
|
17
17
|
import { renderVcmFinalAcceptanceSkillRules } from "../templates/harness/vcm-final-acceptance-skill.js";
|
|
18
18
|
import { renderVcmHarnessBootstrapSkillRules } from "../templates/harness/vcm-harness-bootstrap-skill.js";
|
|
19
19
|
import { renderVcmLongRunningValidationSkillRules } from "../templates/harness/vcm-long-running-validation-skill.js";
|
|
20
|
+
import { renderVcmProposeMemorySkillRules } from "../templates/harness/vcm-propose-memory-skill.js";
|
|
20
21
|
import { renderVcmReportHarnessIssueSkillRules } from "../templates/harness/vcm-report-harness-issue-skill.js";
|
|
21
22
|
import { renderVcmRouteMessageSkillRules } from "../templates/harness/vcm-route-message-skill.js";
|
|
22
23
|
import { submitTerminalInput } from "../runtime/terminal-submit.js";
|
|
@@ -142,6 +143,14 @@ const HARNESS_FILES = [
|
|
|
142
143
|
ownership: "whole-file",
|
|
143
144
|
renderRules: renderVcmReportHarnessIssueSkillRules
|
|
144
145
|
},
|
|
146
|
+
{
|
|
147
|
+
kind: "skill-vcm-propose-memory",
|
|
148
|
+
path: ".claude/skills/vcm-propose-memory/SKILL.md",
|
|
149
|
+
title: "VCM Propose Memory Skill",
|
|
150
|
+
frontmatter: renderSkillFrontmatter("vcm-propose-memory", "Use only when VCM requests a role memory proposal during Task Harness Review."),
|
|
151
|
+
ownership: "whole-file",
|
|
152
|
+
renderRules: renderVcmProposeMemorySkillRules
|
|
153
|
+
},
|
|
145
154
|
{
|
|
146
155
|
kind: "agent-gate-reviewer",
|
|
147
156
|
path: ".claude/agents/gate-reviewer.md",
|
|
@@ -77,12 +77,10 @@ export function createRuntimeCoordinatorService(deps) {
|
|
|
77
77
|
else {
|
|
78
78
|
await deps.translationService.stopTask(taskRepoRoot, activeTask.taskSlug).catch(() => undefined);
|
|
79
79
|
}
|
|
80
|
-
await reconcileAutoMemory(repoRoot, activeTask);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
await maybeStartTaskHarnessRetrospective(repoRoot, activeTask);
|
|
85
|
-
}
|
|
80
|
+
await reconcileAutoMemory(repoRoot, activeTask, preferences.autoTaskHarnessReviewEnabled ? "auto" : undefined);
|
|
81
|
+
const memoryReadiness = await getTaskRetrospectiveMemoryReadiness(repoRoot, activeTask);
|
|
82
|
+
if ((preferences.autoTaskHarnessReviewEnabled || memoryReadiness.trigger) && memoryReadiness.ready) {
|
|
83
|
+
await maybeStartTaskHarnessRetrospective(repoRoot, activeTask, memoryReadiness.trigger ?? "auto");
|
|
86
84
|
}
|
|
87
85
|
return { activeTask, gatewayStatus };
|
|
88
86
|
});
|
|
@@ -169,7 +167,7 @@ export function createRuntimeCoordinatorService(deps) {
|
|
|
169
167
|
throw error;
|
|
170
168
|
}
|
|
171
169
|
}
|
|
172
|
-
async function maybeStartTaskHarnessRetrospective(repoRoot, task) {
|
|
170
|
+
async function maybeStartTaskHarnessRetrospective(repoRoot, task, trigger) {
|
|
173
171
|
const stateRoot = await deps.getStateRoot(repoRoot);
|
|
174
172
|
const taskRepoRoot = getTaskRuntimeRepoRoot(task);
|
|
175
173
|
const roundState = await deps.roundService.getSessionRoundState({
|
|
@@ -188,7 +186,7 @@ export function createRuntimeCoordinatorService(deps) {
|
|
|
188
186
|
taskSlug: task.taskSlug,
|
|
189
187
|
taskRepoRoot,
|
|
190
188
|
handoffDir: task.handoffDir,
|
|
191
|
-
trigger
|
|
189
|
+
trigger
|
|
192
190
|
});
|
|
193
191
|
}
|
|
194
192
|
catch (error) {
|
|
@@ -198,7 +196,7 @@ export function createRuntimeCoordinatorService(deps) {
|
|
|
198
196
|
throw error;
|
|
199
197
|
}
|
|
200
198
|
}
|
|
201
|
-
async function reconcileAutoMemory(repoRoot, task) {
|
|
199
|
+
async function reconcileAutoMemory(repoRoot, task, requestTrigger) {
|
|
202
200
|
const stateRoot = await deps.getStateRoot(repoRoot);
|
|
203
201
|
const taskRepoRoot = getTaskRuntimeRepoRoot(task);
|
|
204
202
|
const roundState = await deps.roundService.getSessionRoundState({
|
|
@@ -212,6 +210,7 @@ export function createRuntimeCoordinatorService(deps) {
|
|
|
212
210
|
taskRepoRoot,
|
|
213
211
|
taskSlug: task.taskSlug,
|
|
214
212
|
handoffDir: task.handoffDir,
|
|
213
|
+
requestTrigger,
|
|
215
214
|
roundReady: roundState.status === "stopped"
|
|
216
215
|
&& Boolean(roundState.roundId)
|
|
217
216
|
&& roundState.roleRecovery?.status !== "failed"
|
|
@@ -66,7 +66,7 @@ ${renderRoleMemoryRules("architect")}
|
|
|
66
66
|
|
|
67
67
|
- Plan the full accepted task scope routed by PM.
|
|
68
68
|
- \`architecture-plan.md\` must describe the complete implementation for that scope.
|
|
69
|
-
- Do not create internal delivery stages, task-splitting suggestions, or follow-up scope
|
|
69
|
+
- Do not create internal delivery stages, task-splitting suggestions, or follow-up scope.
|
|
70
70
|
- Implementation order may be described, but it must not defer requested scope.
|
|
71
71
|
|
|
72
72
|
### Debug Mode
|
|
@@ -8,6 +8,8 @@ export function renderRootClaudeHarnessRules() {
|
|
|
8
8
|
- \`vcm-route-message\` is the only channel for PM-hub dispatch and reporting among project-manager, architect, coder, and tester. Gate Review and tool-role work use their dedicated VCM skills and controllers. Follow the route skill's write-then-stop rule.
|
|
9
9
|
- Use \`vcm-long-running-validation\` for long-running validation. Follow the background job limits below.
|
|
10
10
|
- Use \`vcm-report-harness-issue\` when you notice a reusable VCM harness problem. Record feedback; do not contact Harness Engineer directly.
|
|
11
|
+
- Treat \`.ai/vcm/memory/**\` as read-only. Use \`vcm-propose-memory\` only when VCM assigns a memory proposal during Task Harness Review.
|
|
12
|
+
- Only the user may approve scope reduction, skipped required validation, Gate Review skip or override, skipped required docs sync, accepted unresolved task-scope risk, or weakening of baseline Harness rules. PM may record and route the user's approval but cannot grant it.
|
|
11
13
|
- 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.
|
|
12
14
|
|
|
13
15
|
## VCM Harness Scope
|
|
@@ -101,7 +101,7 @@ Decision: ready_for_review|incomplete|failed
|
|
|
101
101
|
- Coder validation is limited to baseline unit-level and fast L0/L1 checks; do not run L2/L3/L4, smoke, integration, or E2E validation unless the role message explicitly assigns a targeted fast L2 check.
|
|
102
102
|
- Run available L0/L1 validation after implementation.
|
|
103
103
|
- Compile, typecheck, or L0/L1 failure is the signal to report; predicted failure is not.
|
|
104
|
-
- If required compile/typecheck/L0/L1 validation cannot run or cannot complete, write \`Decision: failed
|
|
104
|
+
- If required compile/typecheck/L0/L1 validation cannot run or cannot complete, write \`Decision: failed\`. If the user explicitly approved continuing without the exact check, record the approval and reason; the approval does not change Coder's decision.
|
|
105
105
|
- Do not make tests pass by weakening assertions, skipping tests, hardcoding success, bypassing real behavior paths, or adding test-only production behavior.
|
|
106
106
|
|
|
107
107
|
### Failure Reporting And Continuation
|
|
@@ -48,7 +48,7 @@ You are \`vcm-coder-worker\`, a bounded implementation worker invoked by Coder.
|
|
|
48
48
|
- Run assigned L0/L1 checks in the foreground. Worker checks are module-scoped and treated as safe fast validation: never use \`.ai/tools/run-long-check\` or \`.ai/tools/watch-job\`, and the switch-to-skill rule for long commands does not apply inside worker runs.
|
|
49
49
|
- Do not make tests pass by weakening assertions, skipping tests, hardcoding success, bypassing real behavior paths, or adding test-only production behavior.
|
|
50
50
|
- Report failure only from missing assigned targets, compile/typecheck failure, assigned L0/L1 failure, or a concrete inability to run assigned-module tests.
|
|
51
|
-
- If required assigned compile/typecheck/L0/L1 checks cannot run or cannot complete, update worker state to \`failed
|
|
51
|
+
- If required assigned compile/typecheck/L0/L1 checks cannot run or cannot complete, update worker state to \`failed\`. If the user explicitly approved continuing without the exact check, record the approval and reason; the approval does not change the worker state.
|
|
52
52
|
|
|
53
53
|
### Git
|
|
54
54
|
|
|
@@ -38,9 +38,10 @@ You are not part of the task workflow round state.
|
|
|
38
38
|
permitted bootstrap edits directly in the active task worktree and commit them
|
|
39
39
|
yourself.
|
|
40
40
|
- Retrospective Mode: analyze a completed task for reusable harness problems.
|
|
41
|
-
Do not edit harness
|
|
42
|
-
- Memory Review Mode:
|
|
43
|
-
|
|
41
|
+
Do not edit harness or memory files.
|
|
42
|
+
- Memory Review Mode: when Auto Memory is enabled and VCM starts the memory
|
|
43
|
+
phase of Task Harness Review, review role proposals and write only the review
|
|
44
|
+
output files assigned by VCM.
|
|
44
45
|
- VCM Feedback Mode: draft VCM product, installer, UI, or fixed-template issue
|
|
45
46
|
feedback. Do not submit without explicit in-session user authorization.
|
|
46
47
|
|
|
@@ -50,8 +51,7 @@ You are not part of the task workflow round state.
|
|
|
50
51
|
explicitly asks you to apply an approved harness change.
|
|
51
52
|
- When applying edits, work only in the active task worktree named by VCM. Do not
|
|
52
53
|
edit the base repository root unless VCM explicitly says so.
|
|
53
|
-
- In Proposal Mode
|
|
54
|
-
harness files; only the memory exception above may write files.
|
|
54
|
+
- In Proposal Mode and Retrospective Mode, do not edit files.
|
|
55
55
|
- Commit every applied harness change yourself before ending your turn.
|
|
56
56
|
- Do not overwrite VCM fixed managed blocks.
|
|
57
57
|
- Keep project-specific customization outside VCM managed blocks.
|
|
@@ -64,18 +64,16 @@ You are not part of the task workflow round state.
|
|
|
64
64
|
## Memory Management
|
|
65
65
|
|
|
66
66
|
- Own VCM-managed project memory under \`.ai/vcm/memory/**\`.
|
|
67
|
-
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
- When VCM assigns review output paths, edit only those paths. VCM applies the
|
|
78
|
-
reviewed memory and records the diff.
|
|
67
|
+
- When Auto Memory is disabled, do not request proposals, start Memory Review
|
|
68
|
+
Mode, or update memory.
|
|
69
|
+
- During VCM-assigned Memory Review, verify every role proposal against task
|
|
70
|
+
evidence, merge duplicates, remove stale entries, and keep role-specific
|
|
71
|
+
knowledge in the matching role memory file.
|
|
72
|
+
- Do not record task narrative, temporary state, unverified conclusions, or
|
|
73
|
+
Harness rules in memory.
|
|
74
|
+
- Edit only the review output paths assigned by VCM. Do not edit
|
|
75
|
+
\`.ai/vcm/memory/**\` directly. VCM applies the reviewed output and records the
|
|
76
|
+
diff.
|
|
79
77
|
|
|
80
78
|
## Task Harness Retrospective
|
|
81
79
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const PROJECT_CODING_STANDARDS_RULES = `This file is the shared project baseline for roles that edit production code or tests.
|
|
2
2
|
|
|
3
|
-
Project-specific rules may be added outside the VCM managed block when they make the baseline more precise. Do not weaken these baseline rules without explicit
|
|
3
|
+
Project-specific rules may be added outside the VCM managed block when they make the baseline more precise. Do not weaken these baseline rules without explicit user approval for the exact exception.
|
|
4
4
|
|
|
5
5
|
## Applies To
|
|
6
6
|
|
|
@@ -12,6 +12,7 @@ ${renderRoleMemoryRules("project-manager")}
|
|
|
12
12
|
- Route based on the user request, current VCM task state, and existing handoff status.
|
|
13
13
|
- Do not perform technical analysis; route architecture, implementation, docs, validation, and defect questions to the responsible role defined below.
|
|
14
14
|
- Do not implement production code directly.
|
|
15
|
+
- PM records and routes user approvals. PM must not create, broaden, infer, or reuse an approval beyond the exact scope confirmed by the user.
|
|
15
16
|
|
|
16
17
|
### User Communication
|
|
17
18
|
|
|
@@ -24,11 +25,15 @@ ${renderRoleMemoryRules("project-manager")}
|
|
|
24
25
|
|
|
25
26
|
PM Managed Mode applies only when the user explicitly asks to complete the current task in this mode.
|
|
26
27
|
|
|
27
|
-
- PM must drive the task to completion
|
|
28
|
-
- PM must not
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
28
|
+
- PM must drive the accepted task to completion through the normal VCM flow.
|
|
29
|
+
- PM must not reduce, defer, reinterpret, skip, or move requested work outside the current task.
|
|
30
|
+
- PM must not use workload, task size, context size, implementation difficulty, dependency choice, refactor need, testing effort, or number of iterations as a reason to ask the user.
|
|
31
|
+
- Technical execution questions are handled inside the VCM flow. PM routes them to Architect, Coder, Tester, or Gate Reviewer according to role responsibility.
|
|
32
|
+
- PM may defer non-blocking user-facing questions until the final user report, but only when continuing does not require user intent, external authorization, or a user-approved exception.
|
|
33
|
+
- Deferred questions remain part of the current task report. They must not become follow-up scope unless the user explicitly creates a new task.
|
|
34
|
+
- PM must pause and ask the user only when the task cannot proceed without user intent or real-world authorization: unclear or conflicting requested outcome, required account/secret/test environment/data access, real cost, production permission, sensitive data access, destructive or irreversible real-world action, durable-doc conflict requiring user choice, or a required user-approved exception.
|
|
35
|
+
- Required user-approved exceptions include skipped required validation, Gate Review skip or override, skipped required docs sync, accepted unresolved task-scope risk, or weakening baseline Harness rules.
|
|
36
|
+
- PM records user approvals exactly as given. PM must not create, broaden, infer, or reuse approval.
|
|
32
37
|
- When PM asks the user, the flow must stop and wait for the user's explicit instruction before continuing.
|
|
33
38
|
|
|
34
39
|
### Task Flow Selection
|
|
@@ -146,7 +151,7 @@ When Architect, Coder, or Tester reports a confirmed direct user message:
|
|
|
146
151
|
|
|
147
152
|
- Treat exploratory discussion as non-authoritative unless the report includes explicit user confirmation.
|
|
148
153
|
- Treat local clarification as task context and continue the current flow when it does not change accepted scope, gates, approval state, or routing.
|
|
149
|
-
- Treat confirmed scope, plan, priority, approval, external authorization, or next-route changes as
|
|
154
|
+
- Treat confirmed scope, plan, priority, approval, external authorization, or next-route changes as user-authorized inputs. PM records them and owns only the resulting workflow routing.
|
|
150
155
|
- If the confirmed message changes accepted task scope, make the scope change explicit before continuing.
|
|
151
156
|
- If the confirmed message is only a small clarification for the active role, relay it back with Simple User Relay.
|
|
152
157
|
|
|
@@ -185,13 +190,13 @@ When Architect, Coder, or Tester reports a confirmed direct user message:
|
|
|
185
190
|
- If a role completes a coherent slice and the remaining work still matches the current route, dispatch the same role again.
|
|
186
191
|
- Do not accept workload, session length, or context size as a reason to change the architect plan.
|
|
187
192
|
- Route back to architect only for technical mismatch with the approved plan, not for workload or session-size reasons.
|
|
188
|
-
- Do not advance to the next gate until the current gate is explicitly complete or
|
|
193
|
+
- Do not advance to the next gate until the current gate is explicitly complete or the exact exception has explicit user approval. A Gate Review exception is valid only when VCM records the user's skip or override action.
|
|
189
194
|
|
|
190
195
|
### Final Acceptance
|
|
191
196
|
|
|
192
197
|
- Use the \`vcm-final-acceptance\` skill only to close a complete code-delivery flow, including a primary Debug or Architecture Diagnosis flow that produced code changes.
|
|
193
198
|
- Do not run Final Acceptance for docs-only, validation-only, Communication-only, PR-prep, analysis-only Diagnosis, or any Debug/Diagnosis branch inside another flow.
|
|
194
|
-
- Start final acceptance only after Tester, required Gate Reviews, and required docs-sync gates pass or
|
|
199
|
+
- Start final acceptance only after Tester, required Gate Reviews, and required docs-sync gates pass, or explicit user approval is recorded for each exact exception. Gate Review skip or override is valid only when recorded by VCM from the user's action.
|
|
195
200
|
- Confirm applicable evidence exists: architecture plan or architecture diagnosis when required, test result, required Gate Review decisions, docs-sync decision when required, unresolved risks, known-issues disposition, and cleanup status.
|
|
196
201
|
- Check evidence presence, ownership, currency, and explicit result only; do not judge technical design quality, code quality, test adequacy, or documentation correctness during final acceptance.
|
|
197
202
|
- If final acceptance finds missing evidence, unresolved risk, or required user approval, route it to the responsible role or user before closing the task.
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
export function renderRoleMemoryRules(role) {
|
|
2
|
+
const proposalRule = role === "harness-engineer"
|
|
3
|
+
? `Treat \`.ai/vcm/memory/**\` as read-only during role turns. Update memory
|
|
4
|
+
only through VCM-assigned Memory Review output paths or explicit user edits in
|
|
5
|
+
Harness Studio. When Auto Memory is disabled, do not initiate memory proposals,
|
|
6
|
+
reviews, or updates.`
|
|
7
|
+
: `Treat \`.ai/vcm/memory/**\` as read-only. Do not create, edit, or delete
|
|
8
|
+
memory files. Only when VCM explicitly requests a proposal during Task Harness
|
|
9
|
+
Review, use \`vcm-propose-memory\` and write the exact assigned draft path.`;
|
|
2
10
|
return `### Role Memory
|
|
3
11
|
|
|
4
12
|
Before handling work in a session, read \`.ai/vcm/memory/roles/${role}.md\`.
|
|
5
13
|
Read it again after context compaction before continuing.
|
|
6
14
|
|
|
7
15
|
Treat memory as accumulated project context, not authority. Verify it against
|
|
8
|
-
current code, documentation, and task evidence
|
|
16
|
+
current code, documentation, and task evidence.
|
|
17
|
+
|
|
18
|
+
${proposalRule}`;
|
|
9
19
|
}
|
|
@@ -52,8 +52,8 @@ ${renderRoleMemoryRules("tester")}
|
|
|
52
52
|
- Treat architect-flagged public contracts, migrations, auth, data flow, routing, or dependency changes as inputs for tester-owned validation design.
|
|
53
53
|
- Record skipped L3 checks in \`.ai/vcm/handoffs/test-report.md\` with the reason.
|
|
54
54
|
- Treat validation coverage gaps for accepted task scope, changed behavior, or required public contracts as blocking validation issues; \`Test Result: pass\` cannot include them.
|
|
55
|
-
- Record only existing, unrelated, non-required project limitations
|
|
56
|
-
- If a required validation check is skipped or cannot complete, \`Test Result\` must be \`fail
|
|
55
|
+
- Record only existing, unrelated, non-required project limitations as non-blocking coverage notes, and state why they do not affect current task validation.
|
|
56
|
+
- If a required validation check is skipped or cannot complete, \`Test Result\` must be \`fail\`. If the user explicitly approved continuing without the exact check, record the approval and reason; the approval does not change Tester's result.
|
|
57
57
|
- Update \`docs/TESTING.md\` when validation strategy, commands, level mapping, integration/E2E case definitions, selection rules, final-validation cleanup, test gaps, or test expectations change.
|
|
58
58
|
|
|
59
59
|
### Testing Documentation
|
|
@@ -43,7 +43,7 @@ Review the changed file list only, then classify files:
|
|
|
43
43
|
|
|
44
44
|
- expected files: directly named by the user request, route message, durable plan, architecture plan, or architecture diagnosis
|
|
45
45
|
- supporting files: tests, fixtures, generated context, docs, or wiring needed for expected files
|
|
46
|
-
- approved deviations: files explained by Replan, tester follow-up, docs-sync, or explicit user
|
|
46
|
+
- approved deviations: files explained by Replan, tester follow-up, docs-sync, or explicit user approval
|
|
47
47
|
- unexplained files: files with no traceable reason in the task evidence
|
|
48
48
|
- high-risk unexpected files: auth, permissions, payment, billing, schema, migrations, data deletion, secrets, dependencies, lockfiles, broad generated artifacts, or broad formatting churn
|
|
49
49
|
|
|
@@ -55,14 +55,14 @@ High-risk unexpected files require explicit user approval or architect Replan be
|
|
|
55
55
|
|
|
56
56
|
Check:
|
|
57
57
|
|
|
58
|
-
- required route was followed, or an explicit exception is recorded
|
|
58
|
+
- required route was followed, or an explicit user-approved exception is recorded
|
|
59
59
|
- required handoff artifacts exist and are current
|
|
60
60
|
- architecture plan, Architecture Diagnosis, Replan, or architect follow-up completion is recorded when required by the flow
|
|
61
61
|
- tester report records \`Test Result: pass|fail\`, validation commands, results, and skipped checks with reasons
|
|
62
|
-
- required Gate Reviews are approved,
|
|
63
|
-
- Gate Review enable state is confirmed authoritatively: do not infer that no Gate Reviews were required from an absent or empty \`.ai/vcm/gate-reviews/index.json\`. When Gate Review is enabled, a missing index or a required gate without a recorded decision means the gate was skipped — run the matching command from the \`vcm-gate-review\` skill, including the code source for \`code-diff\`, and do not accept until each required gate returns \`approve\`/\`already_approved\`, \`disabled\`/\`not_required\`, or a recorded skip/override
|
|
62
|
+
- required Gate Reviews are approved, or skipped/overridden through a VCM-recorded user action
|
|
63
|
+
- Gate Review enable state is confirmed authoritatively: do not infer that no Gate Reviews were required from an absent or empty \`.ai/vcm/gate-reviews/index.json\`. When Gate Review is enabled, a missing index or a required gate without a recorded decision means the gate was skipped — run the matching command from the \`vcm-gate-review\` skill, including the code source for \`code-diff\`, and do not accept until each required gate returns \`approve\`/\`already_approved\`, \`disabled\`/\`not_required\`, or a VCM-recorded user skip/override
|
|
64
64
|
- docs-sync report records docs updated, docs intentionally left unchanged, or required follow-up when docs sync was required
|
|
65
|
-
- known issues are either resolved, promoted to durable docs by architect, or explicitly accepted
|
|
65
|
+
- known issues are either resolved, promoted to durable docs by architect, or explicitly accepted by the user
|
|
66
66
|
- temporary task state is ready to clean after durable facts are promoted
|
|
67
67
|
|
|
68
68
|
## Decisions
|
|
@@ -61,7 +61,7 @@ This skill is an operating procedure. It does not replace the deterministic VCM
|
|
|
61
61
|
|
|
62
62
|
- The shared baseline lives inside the VCM managed block and is installer-maintained; do not edit it.
|
|
63
63
|
- Add project-specific implementation rules outside the managed block (for example under \`Project Coding Standards\`) only when they make the shared baseline more precise.
|
|
64
|
-
- Do not weaken the baseline rules without explicit
|
|
64
|
+
- Do not weaken the baseline rules without explicit user approval for the exact exception.
|
|
65
65
|
- Keep role workflow rules out of this file; role routing, Gate Review, Final Acceptance, and role-specific handoff rules belong in role definitions or skills.
|
|
66
66
|
|
|
67
67
|
### \`docs/ARCHITECTURE.md\`
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function renderVcmProposeMemorySkillRules() {
|
|
2
|
+
return `Use this skill only when VCM explicitly requests a memory proposal during Task
|
|
3
|
+
Harness Review and provides an exact draft path.
|
|
4
|
+
|
|
5
|
+
## Rules
|
|
6
|
+
|
|
7
|
+
- Treat \`.ai/vcm/memory/**\` as read-only. This skill creates a proposal; it
|
|
8
|
+
never edits active memory.
|
|
9
|
+
- Write only to the exact draft path assigned by VCM. The path must be under
|
|
10
|
+
\`.ai/vcm/memory-review/runs/<run-id>/drafts/\` in the active task worktree.
|
|
11
|
+
- If VCM did not provide a draft path, do not create a proposal.
|
|
12
|
+
- Propose only verified, durable, reusable project knowledge supported by task
|
|
13
|
+
evidence.
|
|
14
|
+
- Do not record task narrative, temporary state, unverified conclusions, or
|
|
15
|
+
Harness rules.
|
|
16
|
+
- Do not edit handoff artifacts or route messages from this skill.
|
|
17
|
+
|
|
18
|
+
## Draft Format
|
|
19
|
+
|
|
20
|
+
\`\`\`markdown
|
|
21
|
+
# Memory Proposal
|
|
22
|
+
Decision: update | no-change
|
|
23
|
+
|
|
24
|
+
## Add
|
|
25
|
+
|
|
26
|
+
## Update
|
|
27
|
+
|
|
28
|
+
## Remove
|
|
29
|
+
|
|
30
|
+
## Evidence
|
|
31
|
+
\`\`\`
|
|
32
|
+
|
|
33
|
+
Use \`Decision: no-change\` when the completed task produced no qualifying
|
|
34
|
+
memory. End the turn after writing the assigned draft.`;
|
|
35
|
+
}
|