vibe-coding-master 0.8.13 → 0.9.1

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.
Files changed (44) hide show
  1. package/README.md +7 -3
  2. package/dist/backend/adapters/claude-adapter.js +2 -1
  3. package/dist/backend/cli/install-vcm-harness.js +66 -16
  4. package/dist/backend/gateway/gateway-service.js +5 -3
  5. package/dist/backend/runtime/terminal-submit.js +1 -0
  6. package/dist/backend/server.js +14 -4
  7. package/dist/backend/services/app-settings-service.js +3 -2
  8. package/dist/backend/services/auto-memory-service.js +4 -3
  9. package/dist/backend/services/claude-hook-service.js +6 -0
  10. package/dist/backend/services/claude-transcript-service.js +2 -13
  11. package/dist/backend/services/claude-version-check.js +87 -0
  12. package/dist/backend/services/gate-review-service.js +46 -8
  13. package/dist/backend/services/harness-service.js +41 -20
  14. package/dist/backend/services/message-service.js +30 -6
  15. package/dist/backend/services/project-service.js +8 -2
  16. package/dist/backend/services/runtime-recovery-service.js +36 -9
  17. package/dist/backend/services/session-service.js +10 -19
  18. package/dist/backend/services/task-close-service.js +1 -0
  19. package/dist/backend/services/terminal-process-exit-service.js +4 -1
  20. package/dist/backend/services/workflow-control-service.js +55 -11
  21. package/dist/backend/templates/harness/architect-worker-frontmatter.js +33 -0
  22. package/dist/backend/templates/harness/check-scaffold-ledger.js +480 -511
  23. package/dist/backend/templates/harness/gate-review.js +676 -643
  24. package/dist/backend/templates/harness/node-tool-runtime.js +102 -0
  25. package/dist/backend/templates/harness/project-owned-history.js +21 -0
  26. package/dist/backend/templates/harness/resolve-durable-doc-assignment.js +49 -55
  27. package/dist/backend/templates/harness/restart-architect-skill.js +49 -58
  28. package/dist/backend/templates/harness/vcm-ask-user-skill.js +57 -59
  29. package/dist/backend/templates/harness/vcm-task-state-skill.js +66 -72
  30. package/dist/shared/types/app-settings.js +31 -0
  31. package/dist-frontend/assets/index-Bs4g_1yF.css +32 -0
  32. package/dist-frontend/assets/{index-DqANomt1.js → index-CjM9OqZh.js} +41 -41
  33. package/dist-frontend/index.html +2 -2
  34. package/package.json +1 -1
  35. package/scripts/harness-tools/check-durable-docs +332 -298
  36. package/scripts/harness-tools/generate-module-index +1047 -512
  37. package/scripts/harness-tools/generate-public-surface +1231 -1069
  38. package/scripts/harness-tools/package.json +3 -0
  39. package/scripts/harness-tools/run-long-check +608 -531
  40. package/scripts/harness-tools/vcm-artifact +181 -113
  41. package/scripts/harness-tools/vcm-bash-guard +839 -605
  42. package/scripts/harness-tools/vcm-subagent-guard +67 -63
  43. package/scripts/harness-tools/watch-job +313 -238
  44. package/dist-frontend/assets/index-xgiQeUD5.css +0 -32
@@ -1,114 +1,182 @@
1
- #!/usr/bin/env python3
2
- """Submit a VCM-managed Markdown artifact through the VCM backend."""
3
-
4
- import argparse
5
- import json
6
- import os
7
- from pathlib import Path
8
- import sys
9
- import urllib.error
10
- import urllib.parse
11
- import urllib.request
12
-
13
- def parse_args() -> argparse.Namespace:
14
- parser = argparse.ArgumentParser(
15
- description="Validate and atomically write a VCM-managed artifact."
16
- )
17
- parser.add_argument("kind", help="VCM-managed artifact kind.")
18
- parser.add_argument("--file", required=True, help="Candidate Markdown file.")
19
- parser.add_argument("--mode", choices=("draft", "final"), default="final")
20
- parser.add_argument(
21
- "--path",
22
- help="Repository-relative VCM-assigned destination; never an absolute path. VCM selects the artifact's repository root.",
23
- )
24
- parser.add_argument(
25
- "--keep-candidate",
26
- action="store_true",
27
- help="Keep the candidate after a successful submission.",
28
- )
29
- return parser.parse_args()
30
-
31
-
32
- def required_env(name: str) -> str:
33
- value = os.environ.get(name, "").strip()
34
- if not value:
35
- fail(f"{name} is required. Run this tool from an active VCM role Session.")
36
- return value
37
-
38
-
39
- def fail(message: str) -> None:
40
- print(f"VCM artifact submission failed: {message}", file=sys.stderr)
41
- raise SystemExit(1)
42
-
43
-
44
- def error_text(raw: str) -> str:
45
- try:
46
- payload = json.loads(raw)
47
- except (ValueError, TypeError):
48
- return raw.strip() or "VCM backend returned an empty error."
49
- if isinstance(payload, dict):
50
- message = payload.get("message")
51
- hint = payload.get("hint")
52
- if isinstance(payload.get("error"), dict):
53
- message = payload["error"].get("message", message)
54
- hint = payload["error"].get("hint", hint)
55
- parts = [str(value).strip() for value in (message, hint) if value]
56
- if parts:
57
- return "\n".join(parts)
58
- return raw.strip() or "VCM backend rejected the artifact."
59
-
60
-
61
- def main() -> int:
62
- args = parse_args()
63
-
64
- candidate = Path(args.file).expanduser()
65
- if not candidate.is_file():
66
- fail(f"candidate does not exist: {candidate}")
67
- content = candidate.read_text(encoding="utf-8")
68
- if not content.strip():
69
- fail("candidate is empty.")
70
-
71
- api_url = required_env("VCM_API_URL").rstrip("/")
72
- task_slug = required_env("VCM_TASK_SLUG")
73
- payload = {
74
- "kind": args.kind,
75
- "mode": args.mode,
76
- "role": required_env("VCM_ROLE"),
77
- "runtimeSessionToken": required_env("VCM_RUNTIME_SESSION_TOKEN"),
78
- "content": content,
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ // Submit a VCM-managed Markdown artifact through the VCM backend.
4
+
5
+ const fs = require("node:fs");
6
+ const os = require("node:os");
7
+ const path = require("node:path");
8
+
9
+ function fail(message) {
10
+ process.stderr.write("VCM artifact submission failed: " + message + "\n");
11
+ process.exit(1);
12
+ }
13
+
14
+ function usageError(message) {
15
+ process.stderr.write(
16
+ "usage: vcm-artifact [-h] --file FILE [--mode {draft,final}] [--path PATH] [--keep-candidate] kind\n"
17
+ + "vcm-artifact: error: " + message + "\n"
18
+ );
19
+ process.exit(2);
20
+ }
21
+
22
+ function parseArgs(argv) {
23
+ const args = { kind: undefined, file: undefined, mode: "final", path: undefined, keepCandidate: false };
24
+ for (let index = 0; index < argv.length; index += 1) {
25
+ const argument = argv[index];
26
+ if (argument === "-h" || argument === "--help") {
27
+ process.stdout.write(
28
+ "usage: vcm-artifact [-h] --file FILE [--mode {draft,final}] [--path PATH] [--keep-candidate] kind\n\n"
29
+ + "Validate and atomically write a VCM-managed artifact.\n\n"
30
+ + " kind VCM-managed artifact kind.\n"
31
+ + " --file FILE Candidate Markdown file.\n"
32
+ + " --mode {draft,final}\n"
33
+ + " --path PATH Repository-relative VCM-assigned destination; never an absolute path. VCM selects the artifact's repository root.\n"
34
+ + " --keep-candidate Keep the candidate after a successful submission.\n"
35
+ );
36
+ process.exit(0);
79
37
  }
80
- if args.path:
81
- payload["path"] = args.path
82
-
83
- request = urllib.request.Request(
84
- f"{api_url}/api/tasks/{urllib.parse.quote(task_slug, safe='')}/artifacts/submit",
85
- data=json.dumps(payload).encode("utf-8"),
86
- headers={"content-type": "application/json"},
87
- method="POST",
88
- )
89
- try:
90
- with urllib.request.urlopen(request, timeout=30) as response:
91
- raw = response.read().decode("utf-8")
92
- except urllib.error.HTTPError as error:
93
- fail(error_text(error.read().decode("utf-8", errors="replace")))
94
- except urllib.error.URLError as error:
95
- fail(f"VCM backend could not be reached at {api_url}: {error.reason}")
96
-
97
- try:
98
- result = json.loads(raw)
99
- except ValueError:
100
- fail("VCM backend returned invalid JSON.")
101
- if not isinstance(result, dict) or result.get("ok") is not True:
102
- fail(error_text(raw))
103
-
104
- if not args.keep_candidate:
105
- candidate.unlink(missing_ok=True)
106
- print(
107
- f"VCM artifact accepted: {result.get('kind')} -> {result.get('path')} "
108
- f"({result.get('mode')}, {result.get('status')})"
109
- )
110
- return 0
111
-
112
-
113
- if __name__ == "__main__":
114
- raise SystemExit(main())
38
+ if (argument === "--keep-candidate") {
39
+ args.keepCandidate = true;
40
+ continue;
41
+ }
42
+ const separator = argument.indexOf("=");
43
+ const name = argument.startsWith("--") && separator >= 0 ? argument.slice(0, separator) : argument;
44
+ if (name === "--file" || name === "--mode" || name === "--path") {
45
+ let value;
46
+ if (separator >= 0 && argument.startsWith("--")) {
47
+ value = argument.slice(separator + 1);
48
+ } else {
49
+ if (index + 1 >= argv.length) {
50
+ usageError("argument " + name + ": expected one argument");
51
+ }
52
+ index += 1;
53
+ value = argv[index];
54
+ }
55
+ if (name === "--mode" && value !== "draft" && value !== "final") {
56
+ usageError("argument --mode: invalid choice: '" + value + "' (choose from 'draft', 'final')");
57
+ }
58
+ args[name.slice(2)] = value;
59
+ continue;
60
+ }
61
+ if (argument.startsWith("--")) {
62
+ usageError("unrecognized arguments: " + argument);
63
+ }
64
+ if (args.kind !== undefined) {
65
+ usageError("unrecognized arguments: " + argument);
66
+ }
67
+ args.kind = argument;
68
+ }
69
+ const missing = [];
70
+ if (args.kind === undefined) {
71
+ missing.push("kind");
72
+ }
73
+ if (args.file === undefined) {
74
+ missing.push("--file");
75
+ }
76
+ if (missing.length > 0) {
77
+ usageError("the following arguments are required: " + missing.join(", "));
78
+ }
79
+ return args;
80
+ }
81
+
82
+ function requiredEnv(name) {
83
+ const value = (process.env[name] || "").trim();
84
+ if (!value) {
85
+ fail(name + " is required. Run this tool from an active VCM role Session.");
86
+ }
87
+ return value;
88
+ }
89
+
90
+ function errorText(raw) {
91
+ let payload;
92
+ try {
93
+ payload = JSON.parse(raw);
94
+ } catch {
95
+ return raw.trim() || "VCM backend returned an empty error.";
96
+ }
97
+ if (payload && typeof payload === "object" && !Array.isArray(payload)) {
98
+ let message = payload.message;
99
+ let hint = payload.hint;
100
+ if (payload.error && typeof payload.error === "object") {
101
+ message = payload.error.message ?? message;
102
+ hint = payload.error.hint ?? hint;
103
+ }
104
+ const parts = [message, hint].filter(Boolean).map((value) => String(value).trim());
105
+ if (parts.length > 0) {
106
+ return parts.join("\n");
107
+ }
108
+ }
109
+ return raw.trim() || "VCM backend rejected the artifact.";
110
+ }
111
+
112
+ function expandUser(file) {
113
+ return file === "~" || file.startsWith("~/") ? path.join(os.homedir(), file.slice(1)) : file;
114
+ }
115
+
116
+ async function main() {
117
+ const args = parseArgs(process.argv.slice(2));
118
+
119
+ const candidate = expandUser(args.file);
120
+ let stat;
121
+ try {
122
+ stat = fs.statSync(candidate);
123
+ } catch {
124
+ stat = undefined;
125
+ }
126
+ if (!stat || !stat.isFile()) {
127
+ fail("candidate does not exist: " + candidate);
128
+ }
129
+ const content = fs.readFileSync(candidate, "utf8");
130
+ if (!content.trim()) {
131
+ fail("candidate is empty.");
132
+ }
133
+
134
+ const apiUrl = requiredEnv("VCM_API_URL").replace(/\/+$/, "");
135
+ const taskSlug = requiredEnv("VCM_TASK_SLUG");
136
+ const payload = {
137
+ kind: args.kind,
138
+ mode: args.mode,
139
+ role: requiredEnv("VCM_ROLE"),
140
+ runtimeSessionToken: requiredEnv("VCM_RUNTIME_SESSION_TOKEN"),
141
+ content
142
+ };
143
+ if (args.path) {
144
+ payload.path = args.path;
145
+ }
146
+
147
+ let response;
148
+ try {
149
+ response = await fetch(apiUrl + "/api/tasks/" + encodeURIComponent(taskSlug) + "/artifacts/submit", {
150
+ method: "POST",
151
+ headers: { "content-type": "application/json" },
152
+ body: JSON.stringify(payload),
153
+ signal: AbortSignal.timeout(30000)
154
+ });
155
+ } catch (error) {
156
+ const cause = error && error.cause;
157
+ fail("VCM backend could not be reached at " + apiUrl + ": " + ((cause && (cause.message || cause.code)) || error.message));
158
+ }
159
+ const raw = await response.text();
160
+ if (!response.ok) {
161
+ fail(errorText(raw));
162
+ }
163
+
164
+ let result;
165
+ try {
166
+ result = JSON.parse(raw);
167
+ } catch {
168
+ fail("VCM backend returned invalid JSON.");
169
+ }
170
+ if (!result || typeof result !== "object" || result.ok !== true) {
171
+ fail(errorText(raw));
172
+ }
173
+
174
+ if (!args.keepCandidate) {
175
+ fs.rmSync(candidate, { force: true });
176
+ }
177
+ process.stdout.write(
178
+ "VCM artifact accepted: " + result.kind + " -> " + result.path + " (" + result.mode + ", " + result.status + ")\n"
179
+ );
180
+ }
181
+
182
+ main();