vibe-coding-master 0.7.45 → 0.7.46
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 +3 -1
- package/dist/backend/cli/install-vcm-harness.js +8 -0
- package/dist/backend/services/codex-bridge-integration-service.js +3 -1
- package/dist/backend/services/harness-service.js +2 -0
- package/dist/backend/templates/harness/architect-agent.js +1 -0
- package/dist/backend/templates/harness/coder-agent.js +1 -0
- package/package.json +1 -1
- package/scripts/harness-tools/vcm-subagent-guard +61 -0
- package/scripts/verify-package.mjs +1 -0
package/README.md
CHANGED
|
@@ -284,7 +284,9 @@ from the native child process.
|
|
|
284
284
|
Codex Bridge child processes use a hard context limit and auto-compaction window of
|
|
285
285
|
`258400` tokens. VCM sets Claude Code's proactive compaction threshold to `90%`
|
|
286
286
|
(about `232560` tokens), leaving headroom before the Codex API limit. Native
|
|
287
|
-
Claude sessions receive no VCM-owned context override.
|
|
287
|
+
Claude sessions receive no VCM-owned context override. Bridge-backed subagents
|
|
288
|
+
inherit the selected GPT model; native Architect scaffold workers continue to
|
|
289
|
+
use `opus`.
|
|
288
290
|
|
|
289
291
|
Resume keeps the provider recorded by the existing Session. Use Restart when
|
|
290
292
|
switching between native Claude and Codex Bridge. If the Bridge is disabled,
|
|
@@ -53,11 +53,13 @@ const VCM_HOOK_COMMAND = `sh -c 'if [ -z "\${VCM_TASK_SLUG:-}" ] || [ -z "\${VCM
|
|
|
53
53
|
const VCM_STOP_HOOK_COMMAND = `sh -c 'if [ -z "\${VCM_TASK_SLUG:-}" ] || [ -z "\${VCM_ROLE:-}" ] || [ -z "\${VCM_API_URL:-}" ]; then exit 0; fi; node -e '"'"'let s="";process.stdin.setEncoding("utf8");process.stdin.on("data",d=>s+=d);process.stdin.on("end",()=>{let event={};try{event=s.trim()?JSON.parse(s):{};}catch{event={raw:s};}process.stdout.write(JSON.stringify({taskSlug:process.env.VCM_TASK_SLUG,role:process.env.VCM_ROLE,runtimeSessionToken:process.env.VCM_RUNTIME_SESSION_TOKEN,event}));});'"'"' | curl -fsS --retry 2 --retry-delay 1 --retry-all-errors --connect-timeout 1 --max-time 2 -X POST "\${VCM_API_URL}/api/hooks/claude-code/stop" -H "content-type: application/json" --data-binary @- || true'`;
|
|
54
54
|
const VCM_PERMISSION_REQUEST_HOOK_COMMAND = `sh -c 'if [ -z "\${VCM_TASK_SLUG:-}" ] || [ -z "\${VCM_ROLE:-}" ] || [ -z "\${VCM_API_URL:-}" ]; then exit 0; fi; node -e '"'"'let s="";process.stdin.setEncoding("utf8");process.stdin.on("data",d=>s+=d);process.stdin.on("end",()=>{let event={};try{event=s.trim()?JSON.parse(s):{};}catch{event={raw:s};}process.stdout.write(JSON.stringify({taskSlug:process.env.VCM_TASK_SLUG,role:process.env.VCM_ROLE,runtimeSessionToken:process.env.VCM_RUNTIME_SESSION_TOKEN,event}));});'"'"' | curl -fsS --max-time 5 -X POST "\${VCM_API_URL}/api/hooks/claude-code/permission-request" -H "content-type: application/json" --data-binary @- || true'`;
|
|
55
55
|
const VCM_BASH_GUARD_HOOK_COMMAND = `sh -c 'if [ -z "\${VCM_TASK_SLUG:-}" ] || [ -z "\${VCM_ROLE:-}" ]; then exit 0; fi; guard=""; repo="$(git rev-parse --show-toplevel 2>/dev/null || true)"; if [ -n "$repo" ] && [ -f "$repo/.ai/tools/vcm-bash-guard" ]; then guard="$repo/.ai/tools/vcm-bash-guard"; else cwd="$(pwd -P 2>/dev/null || pwd)"; dir="$cwd"; while [ -n "$dir" ] && [ "$dir" != "/" ]; do if [ -f "$dir/.ai/tools/vcm-bash-guard" ]; then guard="$dir/.ai/tools/vcm-bash-guard"; break; fi; dir="$(dirname "$dir")"; done; if [ -z "$guard" ] && [ -n "\${CLAUDE_PROJECT_DIR:-}" ] && [ -f "\${CLAUDE_PROJECT_DIR}/.ai/tools/vcm-bash-guard" ]; then guard="\${CLAUDE_PROJECT_DIR}/.ai/tools/vcm-bash-guard"; fi; fi; [ -n "$guard" ] || exit 0; python3 "$guard" || exit 0'`;
|
|
56
|
+
const VCM_SUBAGENT_GUARD_HOOK_COMMAND = `sh -c 'if [ -z "\${VCM_TASK_SLUG:-}" ] || [ -z "\${VCM_ROLE:-}" ]; then exit 0; fi; guard=""; repo="$(git rev-parse --show-toplevel 2>/dev/null || true)"; if [ -n "$repo" ] && [ -f "$repo/.ai/tools/vcm-subagent-guard" ]; then guard="$repo/.ai/tools/vcm-subagent-guard"; else cwd="$(pwd -P 2>/dev/null || pwd)"; dir="$cwd"; while [ -n "$dir" ] && [ "$dir" != "/" ]; do if [ -f "$dir/.ai/tools/vcm-subagent-guard" ]; then guard="$dir/.ai/tools/vcm-subagent-guard"; break; fi; dir="$(dirname "$dir")"; done; if [ -z "$guard" ] && [ -n "\${CLAUDE_PROJECT_DIR:-}" ] && [ -f "\${CLAUDE_PROJECT_DIR}/.ai/tools/vcm-subagent-guard" ]; then guard="\${CLAUDE_PROJECT_DIR}/.ai/tools/vcm-subagent-guard"; fi; fi; [ -n "$guard" ] || { printf "%s\\n" "{\\"hookSpecificOutput\\":{\\"hookEventName\\":\\"PreToolUse\\",\\"permissionDecision\\":\\"deny\\",\\"permissionDecisionReason\\":\\"VCM subagent policy is unavailable. Refresh the VCM Harness before invoking subagents.\\"}}"; exit 0; }; python3 "$guard"'`;
|
|
56
57
|
const VCM_BASH_DEFAULT_TIMEOUT_MS = "600000";
|
|
57
58
|
const VCM_AUTO_MEMORY_ENABLED = false;
|
|
58
59
|
const VCM_HOOK_DEFINITIONS = [
|
|
59
60
|
{ eventName: "PreToolUse", matcher: "Bash", command: VCM_BASH_GUARD_HOOK_COMMAND, timeout: 10 },
|
|
60
61
|
{ eventName: "PreToolUse", matcher: "Write|Edit", command: VCM_BASH_GUARD_HOOK_COMMAND, timeout: 10 },
|
|
62
|
+
{ eventName: "PreToolUse", matcher: "Agent", command: VCM_SUBAGENT_GUARD_HOOK_COMMAND, timeout: 10 },
|
|
61
63
|
{ eventName: "UserPromptSubmit", command: VCM_HOOK_COMMAND, timeout: 5 },
|
|
62
64
|
{ eventName: "PreToolUse", command: VCM_HOOK_COMMAND, timeout: 5 },
|
|
63
65
|
{ eventName: "PostToolUse", command: VCM_HOOK_COMMAND, timeout: 5 },
|
|
@@ -416,6 +418,12 @@ const WHOLE_FILES = [
|
|
|
416
418
|
mode: 0o755,
|
|
417
419
|
templatePath: "scripts/harness-tools/vcm-bash-guard"
|
|
418
420
|
},
|
|
421
|
+
{
|
|
422
|
+
path: ".ai/tools/vcm-subagent-guard",
|
|
423
|
+
category: "runtime-tool",
|
|
424
|
+
mode: 0o755,
|
|
425
|
+
templatePath: "scripts/harness-tools/vcm-subagent-guard"
|
|
426
|
+
},
|
|
419
427
|
{
|
|
420
428
|
path: ".ai/tools/vcm-artifact",
|
|
421
429
|
category: "runtime-tool",
|
|
@@ -166,6 +166,7 @@ export function createCodexBridgeIntegrationService(deps) {
|
|
|
166
166
|
CODEX_BRIDGE_CLAUDE_MODEL: modelId,
|
|
167
167
|
ANTHROPIC_SMALL_FAST_MODEL: modelId,
|
|
168
168
|
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY: "1",
|
|
169
|
+
CLAUDE_CODE_SUBAGENT_MODEL: modelId,
|
|
169
170
|
CLAUDE_CODE_MAX_CONTEXT_TOKENS: String(CODEX_BRIDGE_EFFECTIVE_CONTEXT_TOKENS),
|
|
170
171
|
CLAUDE_CODE_AUTO_COMPACT_WINDOW: String(CODEX_BRIDGE_AUTO_COMPACT_WINDOW_TOKENS),
|
|
171
172
|
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: String(CODEX_BRIDGE_AUTO_COMPACT_PERCENT),
|
|
@@ -191,7 +192,8 @@ const BRIDGE_BASE_URL_KEYS = [
|
|
|
191
192
|
];
|
|
192
193
|
const BRIDGE_MODEL_KEYS = [
|
|
193
194
|
"ANTHROPIC_MODEL",
|
|
194
|
-
"ANTHROPIC_SMALL_FAST_MODEL"
|
|
195
|
+
"ANTHROPIC_SMALL_FAST_MODEL",
|
|
196
|
+
"CLAUDE_CODE_SUBAGENT_MODEL"
|
|
195
197
|
];
|
|
196
198
|
const BRIDGE_ONLY_ENV_KEYS = [
|
|
197
199
|
"CODEX_BRIDGE_CLAUDE_MODEL",
|
|
@@ -53,11 +53,13 @@ const VCM_HOOK_COMMAND = `sh -c 'if [ -z "\${VCM_TASK_SLUG:-}" ] || [ -z "\${VCM
|
|
|
53
53
|
const VCM_STOP_HOOK_COMMAND = `sh -c 'if [ -z "\${VCM_TASK_SLUG:-}" ] || [ -z "\${VCM_ROLE:-}" ] || [ -z "\${VCM_API_URL:-}" ]; then exit 0; fi; node -e '"'"'let s="";process.stdin.setEncoding("utf8");process.stdin.on("data",d=>s+=d);process.stdin.on("end",()=>{let event={};try{event=s.trim()?JSON.parse(s):{};}catch{event={raw:s};}process.stdout.write(JSON.stringify({taskSlug:process.env.VCM_TASK_SLUG,role:process.env.VCM_ROLE,runtimeSessionToken:process.env.VCM_RUNTIME_SESSION_TOKEN,event}));});'"'"' | curl -fsS --retry 2 --retry-delay 1 --retry-all-errors --connect-timeout 1 --max-time 2 -X POST "\${VCM_API_URL}/api/hooks/claude-code/stop" -H "content-type: application/json" --data-binary @- || true'`;
|
|
54
54
|
const VCM_PERMISSION_REQUEST_HOOK_COMMAND = `sh -c 'if [ -z "\${VCM_TASK_SLUG:-}" ] || [ -z "\${VCM_ROLE:-}" ] || [ -z "\${VCM_API_URL:-}" ]; then exit 0; fi; node -e '"'"'let s="";process.stdin.setEncoding("utf8");process.stdin.on("data",d=>s+=d);process.stdin.on("end",()=>{let event={};try{event=s.trim()?JSON.parse(s):{};}catch{event={raw:s};}process.stdout.write(JSON.stringify({taskSlug:process.env.VCM_TASK_SLUG,role:process.env.VCM_ROLE,runtimeSessionToken:process.env.VCM_RUNTIME_SESSION_TOKEN,event}));});'"'"' | curl -fsS --max-time 5 -X POST "\${VCM_API_URL}/api/hooks/claude-code/permission-request" -H "content-type: application/json" --data-binary @- || true'`;
|
|
55
55
|
const VCM_BASH_GUARD_HOOK_COMMAND = `sh -c 'if [ -z "\${VCM_TASK_SLUG:-}" ] || [ -z "\${VCM_ROLE:-}" ]; then exit 0; fi; guard=""; repo="$(git rev-parse --show-toplevel 2>/dev/null || true)"; if [ -n "$repo" ] && [ -f "$repo/.ai/tools/vcm-bash-guard" ]; then guard="$repo/.ai/tools/vcm-bash-guard"; else cwd="$(pwd -P 2>/dev/null || pwd)"; dir="$cwd"; while [ -n "$dir" ] && [ "$dir" != "/" ]; do if [ -f "$dir/.ai/tools/vcm-bash-guard" ]; then guard="$dir/.ai/tools/vcm-bash-guard"; break; fi; dir="$(dirname "$dir")"; done; if [ -z "$guard" ] && [ -n "\${CLAUDE_PROJECT_DIR:-}" ] && [ -f "\${CLAUDE_PROJECT_DIR}/.ai/tools/vcm-bash-guard" ]; then guard="\${CLAUDE_PROJECT_DIR}/.ai/tools/vcm-bash-guard"; fi; fi; [ -n "$guard" ] || exit 0; python3 "$guard" || exit 0'`;
|
|
56
|
+
const VCM_SUBAGENT_GUARD_HOOK_COMMAND = `sh -c 'if [ -z "\${VCM_TASK_SLUG:-}" ] || [ -z "\${VCM_ROLE:-}" ]; then exit 0; fi; guard=""; repo="$(git rev-parse --show-toplevel 2>/dev/null || true)"; if [ -n "$repo" ] && [ -f "$repo/.ai/tools/vcm-subagent-guard" ]; then guard="$repo/.ai/tools/vcm-subagent-guard"; else cwd="$(pwd -P 2>/dev/null || pwd)"; dir="$cwd"; while [ -n "$dir" ] && [ "$dir" != "/" ]; do if [ -f "$dir/.ai/tools/vcm-subagent-guard" ]; then guard="$dir/.ai/tools/vcm-subagent-guard"; break; fi; dir="$(dirname "$dir")"; done; if [ -z "$guard" ] && [ -n "\${CLAUDE_PROJECT_DIR:-}" ] && [ -f "\${CLAUDE_PROJECT_DIR}/.ai/tools/vcm-subagent-guard" ]; then guard="\${CLAUDE_PROJECT_DIR}/.ai/tools/vcm-subagent-guard"; fi; fi; [ -n "$guard" ] || { printf "%s\\n" "{\\"hookSpecificOutput\\":{\\"hookEventName\\":\\"PreToolUse\\",\\"permissionDecision\\":\\"deny\\",\\"permissionDecisionReason\\":\\"VCM subagent policy is unavailable. Refresh the VCM Harness before invoking subagents.\\"}}"; exit 0; }; python3 "$guard"'`;
|
|
56
57
|
const VCM_BASH_DEFAULT_TIMEOUT_MS = "600000";
|
|
57
58
|
const VCM_AUTO_MEMORY_ENABLED = false;
|
|
58
59
|
const VCM_HOOK_DEFINITIONS = [
|
|
59
60
|
{ eventName: "PreToolUse", matcher: "Bash", command: VCM_BASH_GUARD_HOOK_COMMAND, timeout: 10 },
|
|
60
61
|
{ eventName: "PreToolUse", matcher: "Write|Edit", command: VCM_BASH_GUARD_HOOK_COMMAND, timeout: 10 },
|
|
62
|
+
{ eventName: "PreToolUse", matcher: "Agent", command: VCM_SUBAGENT_GUARD_HOOK_COMMAND, timeout: 10 },
|
|
61
63
|
{ eventName: "UserPromptSubmit", command: VCM_HOOK_COMMAND, timeout: 5 },
|
|
62
64
|
{ eventName: "PreToolUse", command: VCM_HOOK_COMMAND, timeout: 5 },
|
|
63
65
|
{ eventName: "PostToolUse", command: VCM_HOOK_COMMAND, timeout: 5 },
|
|
@@ -125,6 +125,7 @@ ${renderRoleMemoryRules("architect")}
|
|
|
125
125
|
#### Code Scaffolding
|
|
126
126
|
|
|
127
127
|
- Use the Agent tool to invoke \`vcm-architect-scaffold-worker\` in the foreground after the plan and Scaffold Manifest are complete. Give it the exact plan path and require it to return before this Architect turn continues.
|
|
128
|
+
- Do not invoke any other subagent.
|
|
128
129
|
- Use one scaffold worker. Do not run it in the background or end the Architect turn while it is active.
|
|
129
130
|
- Review the worker commit, actual diff, callable surfaces, marker placement, ledger reconciliation, and L0 results yourself. Architect owns every final scaffold claim and must correct any worker error before marking planning complete.
|
|
130
131
|
- Create or update only the minimum module/file scaffolding needed to make boundaries, callable surfaces, and placeholders unambiguous. Minimum limits depth (no business implementation), never breadth: every \`create\`, \`change\`, and \`delete\` item must be scaffolded.
|
|
@@ -50,6 +50,7 @@ ${renderRoleMemoryRules("coder")}
|
|
|
50
50
|
### Parallel Worker Implementation
|
|
51
51
|
|
|
52
52
|
- Coder may use Claude Code subagents to invoke \`vcm-coder-worker\` for parallel implementation.
|
|
53
|
+
- Do not invoke any other subagent.
|
|
53
54
|
- Use workers when the task has at least 20 \`VCM:CODE\` markers and the marker distribution can form at least two worker-sized groups.
|
|
54
55
|
- Under a complete scaffold, marker implementations are order-independent — signatures, types, and cross-item contracts are frozen by the scaffold — so never serialize worker-sized groups for presumed implementation-order dependencies. When a group's module-scoped checks need peers that are still unimplemented, narrow that worker's assigned validation scope instead of serializing.
|
|
55
56
|
- An item counts as blocked only when a genuine implementation attempt has produced objective compile/check evidence already reported under the failure rules; prediction never blocks an item. A blocked marker item never exempts the remaining markers from worker dispatch.
|
package/package.json
CHANGED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Restrict VCM role sessions to their assigned worker subagents."""
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
ALLOWED_SUBAGENTS = {
|
|
10
|
+
"architect": "vcm-architect-scaffold-worker",
|
|
11
|
+
"coder": "vcm-coder-worker",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def deny(reason: str) -> None:
|
|
16
|
+
print(json.dumps({
|
|
17
|
+
"hookSpecificOutput": {
|
|
18
|
+
"hookEventName": "PreToolUse",
|
|
19
|
+
"permissionDecision": "deny",
|
|
20
|
+
"permissionDecisionReason": reason,
|
|
21
|
+
}
|
|
22
|
+
}))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def main() -> None:
|
|
26
|
+
role = os.environ.get("VCM_ROLE", "").strip()
|
|
27
|
+
if not role:
|
|
28
|
+
return
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
payload = json.load(sys.stdin)
|
|
32
|
+
except (json.JSONDecodeError, OSError):
|
|
33
|
+
deny("VCM could not validate this subagent request because its hook payload is invalid.")
|
|
34
|
+
return
|
|
35
|
+
|
|
36
|
+
if not isinstance(payload, dict):
|
|
37
|
+
deny("VCM could not validate this subagent request because its hook payload is invalid.")
|
|
38
|
+
return
|
|
39
|
+
|
|
40
|
+
if payload.get("tool_name") != "Agent":
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
if payload.get("agent_id"):
|
|
44
|
+
deny("VCM worker subagents may not invoke nested subagents.")
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
tool_input = payload.get("tool_input")
|
|
48
|
+
subagent_type = tool_input.get("subagent_type") if isinstance(tool_input, dict) else None
|
|
49
|
+
allowed = ALLOWED_SUBAGENTS.get(role)
|
|
50
|
+
|
|
51
|
+
if allowed is None:
|
|
52
|
+
deny(f"VCM role `{role}` may not invoke subagents.")
|
|
53
|
+
return
|
|
54
|
+
|
|
55
|
+
if subagent_type != allowed:
|
|
56
|
+
requested = subagent_type if isinstance(subagent_type, str) and subagent_type else "<missing>"
|
|
57
|
+
deny(f"VCM role `{role}` may invoke only `{allowed}`, not `{requested}`.")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
if __name__ == "__main__":
|
|
61
|
+
main()
|
|
@@ -13,6 +13,7 @@ const requiredFiles = [
|
|
|
13
13
|
"scripts/harness-tools/run-long-check",
|
|
14
14
|
"scripts/harness-tools/watch-job",
|
|
15
15
|
"scripts/harness-tools/vcm-bash-guard",
|
|
16
|
+
"scripts/harness-tools/vcm-subagent-guard",
|
|
16
17
|
"scripts/install-vcm-harness.mjs",
|
|
17
18
|
"scripts/uninstall-vcm-harness.mjs",
|
|
18
19
|
"dist/main.js",
|