claude-dev-env 1.62.1 → 1.64.0

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.
@@ -141,15 +141,33 @@ const STANDARDS_EDIT_SCHEMA = {
141
141
  required: ['issueUrl', 'hardeningRepoPath', 'hardeningBranch', 'hardeningEdited', 'summary'],
142
142
  }
143
143
 
144
- const VERDICT_FENCE_STEPS =
145
- `Compute the binding hash for the live surface by running exactly:\n` +
146
- ` "C:\\Python313\\python.exe" "<REPO>/packages/claude-dev-env/hooks/blocking/verification_verdict_store.py" --manifest-hash "<REPO>"\n` +
147
- ` (substitute the REPO path you resolved). That prints a single 64-char hex hash on stdout capture it.\n` +
148
- `Then END your message with a fenced verdict block exactly in this shape, on its own, carrying that hash:\n` +
149
- " ```verdict\n" +
150
- ` {"all_pass": true, "findings": [], "manifest_sha256": "<that hash>"}\n` +
151
- " ```\n" +
152
- ` When verification fails, set all_pass to false and list the unresolved concerns in findings; still include the manifest_sha256. The verdict fence must be the last thing in your message.`
144
+ /**
145
+ * Build the verdict-fence step instructions for a verify agent, binding the
146
+ * surface hash by branch name rather than by a self-resolved cwd. Resolving
147
+ * the branch via `gh pr view` is cwd-immune: it does not matter which worktree
148
+ * the verify agent runs in, so a launcher session whose cwd is a different
149
+ * worktree cannot poison the binding hash.
150
+ * @param {string} prOwner GitHub owner of the repo that holds the branch
151
+ * @param {string} prRepo GitHub repo name
152
+ * @param {number|string} prNumber PR number used to resolve the head branch
153
+ * @returns {string} binding-hash and verdict-fence instructions for a verify prompt
154
+ */
155
+ function buildVerdictFenceSteps(prOwner, prRepo, prNumber) {
156
+ return (
157
+ `Compute the binding hash for the live surface:\n` +
158
+ ` a. Resolve the PR head branch (cwd-immune): run exactly\n` +
159
+ ` gh pr view ${prNumber} --repo ${prOwner}/${prRepo} --json headRefName -q .headRefName\n` +
160
+ ` Capture the branch name printed on stdout.\n` +
161
+ ` b. Run exactly:\n` +
162
+ ` "C:\\Python313\\python.exe" "<REPO>/packages/claude-dev-env/hooks/blocking/verification_verdict_store.py" --manifest-hash-for-branch "<that branch>"\n` +
163
+ ` (substitute the REPO path you resolved for the script path, and the branch name for <that branch>). That prints a single 64-char hex hash on stdout — capture it.\n` +
164
+ `Then END your message with a fenced verdict block exactly in this shape, on its own, carrying that hash:\n` +
165
+ " ```verdict\n" +
166
+ ` {"all_pass": true, "findings": [], "manifest_sha256": "<that hash>"}\n` +
167
+ " ```\n" +
168
+ ` When verification fails, set all_pass to false and list the unresolved concerns in findings; still include the manifest_sha256. The verdict fence must be the last thing in your message.`
169
+ )
170
+ }
153
171
 
154
172
  const CONVERGENCE_SUMMARY_SCHEMA = {
155
173
  type: 'object',
@@ -713,9 +731,9 @@ function verifyFixesInWorkingTree(head, findings, sourceLabel) {
713
731
  `You are the VERIFY step for ${findings.length} finding(s) (${sourceLabel}) on ${prCoordinates}, HEAD ${head}. The edit step left fixes in the working tree, uncommitted. Do NO edits of any kind — verification only; any edit invalidates the verdict you are about to emit.\n\n` +
714
732
  `Findings the working-tree fixes must address:\n${findingsBlock}\n\n` +
715
733
  `Steps:\n` +
716
- `1. Resolve the worktree repo root: REPO=$(git rev-parse --show-toplevel).\n` +
734
+ `1. Resolve the worktree repo root for running tests: REPO=$(git rev-parse --show-toplevel).\n` +
717
735
  `2. Verify the uncommitted working-tree changes resolve every finding above: run the relevant tests and the named gates against the working tree. Read the diff (git diff) and confirm each finding is fixed test-first per CODE_RULES.\n` +
718
- `3. ${VERDICT_FENCE_STEPS}`,
736
+ `3. ${buildVerdictFenceSteps(input.owner, input.repo, input.prNumber)}`,
719
737
  { label: `fix-verify:${sourceLabel}`, phase: 'Converge', agentType: 'code-verifier' },
720
738
  )
721
739
  }
@@ -935,9 +953,9 @@ function verifyRepairChanges(head, failures) {
935
953
  `You are the VERIFY step for the convergence repair on ${prCoordinates}, HEAD ${head}. The edit step left its repair in the working tree (a bot-thread fix uncommitted, and/or a rebase onto origin/main), unpushed. Do NO edits of any kind — verification only; any edit invalidates the verdict you are about to emit.\n\n` +
936
954
  `Concerns the working-tree repair must resolve (the gates the convergence check flagged):\n${failureBlock}\n\n` +
937
955
  `Steps:\n` +
938
- `1. Resolve the worktree repo root: REPO=$(git rev-parse --show-toplevel).\n` +
956
+ `1. Resolve the worktree repo root for running tests: REPO=$(git rev-parse --show-toplevel).\n` +
939
957
  `2. Verify the working tree against origin/main: any bot-thread code fix is correct test-first per CODE_RULES, and a rebase (if any) left a clean, conflict-free tree. Read the diff (git diff origin/main) and run the relevant tests and named gates.\n` +
940
- `3. ${VERDICT_FENCE_STEPS}`,
958
+ `3. ${buildVerdictFenceSteps(input.owner, input.repo, input.prNumber)}`,
941
959
  { label: 'repair-verify', phase: 'Finalize', agentType: 'code-verifier' },
942
960
  )
943
961
  }
@@ -1044,22 +1062,32 @@ function standardsFollowUpEdit(head, findings, sourceLabel) {
1044
1062
  /**
1045
1063
  * Standards-hardening verify step: a code-verifier confirms the uncommitted
1046
1064
  * hooks/rules change staged in the hardening repo blocks the deferred violation
1047
- * classes, computes the binding surface hash for that repo, and ends with a
1048
- * verdict fence as plain assistant text (NO schema) — unlocking the
1065
+ * classes, computes the binding surface hash for that repo by branch (cwd-immune),
1066
+ * and ends with a verdict fence as plain assistant text (NO schema) — unlocking the
1049
1067
  * verified-commit gate for the cross-repo hardening commit. The verifier makes
1050
1068
  * no edits.
1051
1069
  * @param {string} hardeningRepoPath absolute path of the hardening repo checkout the edit staged
1070
+ * @param {string} hardeningBranch the branch in the hardening repo that the edit staged the change on
1052
1071
  * @param {string} sourceLabel short description of where the findings came from
1053
1072
  * @returns {Promise<string>} the verifier transcript carrying the verdict fence
1054
1073
  */
1055
- function verifyHardeningChanges(hardeningRepoPath, sourceLabel) {
1074
+ function verifyHardeningChanges(hardeningRepoPath, hardeningBranch, sourceLabel) {
1056
1075
  return convergeAgent(
1057
1076
  `You are the VERIFY step for an environment-hardening change (${sourceLabel}) staged in the working tree of ${hardeningRepoPath}. The edit step left the hooks/rules edits uncommitted there. Do NO edits of any kind — verification only; any edit invalidates the verdict you are about to emit.\n\n` +
1058
1077
  `Concern the working-tree change must resolve: the edited hooks/rules block the code-standard violation classes from the deferred round at Write/Edit time, and a hook change carries a passing test per CODE_RULES.\n\n` +
1059
1078
  `Steps:\n` +
1060
1079
  `1. cd into ${hardeningRepoPath}, then resolve its repo root: REPO=$(git rev-parse --show-toplevel).\n` +
1061
1080
  `2. Verify the uncommitted working-tree change in REPO: read the diff (git diff) and run the hook/rule tests in that repo, confirming each violation class is now blocked.\n` +
1062
- `3. ${VERDICT_FENCE_STEPS}`,
1081
+ `3. Compute the binding hash for the live surface:\n` +
1082
+ ` The hardening branch is: ${hardeningBranch}\n` +
1083
+ ` Run exactly:\n` +
1084
+ ` "C:\\Python313\\python.exe" "<REPO>/packages/claude-dev-env/hooks/blocking/verification_verdict_store.py" --manifest-hash-for-branch "${hardeningBranch}"\n` +
1085
+ ` (substitute the REPO path you resolved for the script path). That prints a single 64-char hex hash on stdout — capture it.\n` +
1086
+ ` Then END your message with a fenced verdict block exactly in this shape, on its own, carrying that hash:\n` +
1087
+ " ```verdict\n" +
1088
+ ` {"all_pass": true, "findings": [], "manifest_sha256": "<that hash>"}\n` +
1089
+ " ```\n" +
1090
+ ` When verification fails, set all_pass to false and list the unresolved concerns in findings; still include the manifest_sha256. The verdict fence must be the last thing in your message.`,
1063
1091
  { label: `standards-verify:${sourceLabel}`, phase: 'Converge', agentType: 'code-verifier' },
1064
1092
  )
1065
1093
  }
@@ -1123,7 +1151,7 @@ async function spawnStandardsFollowUp(head, findings, sourceLabel) {
1123
1151
  if (editResult?.hardeningEdited !== true || !editResult?.hardeningRepoPath) {
1124
1152
  return { hardeningPrOpened: false }
1125
1153
  }
1126
- const verifyTranscript = await verifyHardeningChanges(editResult.hardeningRepoPath, sourceLabel)
1154
+ const verifyTranscript = await verifyHardeningChanges(editResult.hardeningRepoPath, editResult.hardeningBranch, sourceLabel)
1127
1155
  if (!verdictPassed(verifyTranscript)) {
1128
1156
  return { hardeningPrOpened: false }
1129
1157
  }
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: verified-build
3
+ description: >-
4
+ Runs a code task through the two-phase verified workflow: scoped coder
5
+ agents write the changes (consulting the tool-less code-advisor when
6
+ stuck on a decision), then a fresh-context code-verifier agent re-derives
7
+ and runs every check itself. The verifier's fenced verdict is minted by
8
+ the verifier_verdict_minter hook and unlocks the verified_commit_gate for
9
+ git commit/push. Use for feature implementations, refactors, and bug
10
+ fixes that land behind verification. Triggers: 'verified build', 'run
11
+ this verified', 'two-phase build', 'build and verify', 'verified
12
+ implementation'.
13
+ ---
14
+
15
+ # Verified Build
16
+
17
+ Two phases, hook-enforced: coders write, a fresh-context verifier grades, and `git commit`/`git push` open only on a clean verdict bound to the live change surface.
18
+
19
+ ## Workflow
20
+
21
+ Copy this checklist and check items off as you go:
22
+
23
+ - [ ] **Record baselines.** Before any coder runs: the test command and its exact failure set, plus any other gates the repo names. Scope the test command to the modules the task touches (their test files plus tests importing the changed modules); record a full-suite baseline only when the assignments span multiple modules or multiple coders. The verifier compares against these.
24
+ - [ ] **Scope assignments.** Split the task into file-disjoint assignments; write each as a task text with named checks.
25
+ - [ ] **Spawn coders.** One agent per assignment (`clean-coder` or Sonnet). Tell each: on a decision it can't reasonably solve, consult the tool-less `code-advisor` agent — it returns a plan, a correction, or a stop signal — then resume.
26
+ - [ ] **Settle the tree.** After coders finish: run formatters and any file-rewriting hooks, stage nothing, change nothing more.
27
+ - [ ] **Spawn the verifier last.** Agent tool, `subagent_type: "code-verifier"`, with the task texts, the diff scope, and the recorded baselines. When it stops, the SubagentStop hook mints its verdict.
28
+ - [ ] **Repair only reported findings.** On a failing verdict, spawn repair agents scoped to the findings, then re-spawn the verifier. Repeat until clean.
29
+ - [ ] **Land right away.** One commit, push, draft PR — before anything else touches a file.
30
+
31
+ ## Gotchas
32
+
33
+ - Any file change after the verifier stops moves the surface hash and re-locks the gate — formatter rewrites included. Settle the tree first; land right after the clean verdict.
34
+ - The verdict covers the whole branch surface (merge base to work tree, untracked files included). There is no "verify just my part."
35
+ - The verifier must end with a ```` ```verdict ```` fence. No fence means nothing is minted and the gate stays closed.
36
+ - The minter keys on the agent type string `code-verifier` — spawning the same prompt under another agent type mints nothing.
37
+ - A surface whose every change is a docs/image file (by extension), a Python file whose docstring-stripped AST is unchanged (docstring-, comment-, or formatting-only Python edits), or a pytest test file (`test_*.py`, `*_test.py`, `conftest.py`) is exempt automatically; skip the verifier for those. Comment-only edits in non-Python files are not exempt.
38
+ - Record the test baseline before coders start. Without the exact pre-existing failure set, new breakage hides inside old noise.