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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-coding-master",
3
- "version": "0.7.45",
3
+ "version": "0.7.46",
4
4
  "description": "Local GUI session cockpit for Claude Code role sessions.",
5
5
  "type": "module",
6
6
  "files": [
@@ -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",