vibe-coding-master 0.8.12 → 0.9.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.
- package/README.md +7 -3
- package/dist/backend/cli/install-vcm-harness.js +57 -18
- package/dist/backend/gateway/gateway-service.js +5 -3
- package/dist/backend/runtime/terminal-submit.js +1 -0
- package/dist/backend/server.js +14 -4
- package/dist/backend/services/app-settings-service.js +3 -2
- package/dist/backend/services/auto-memory-service.js +6 -4
- package/dist/backend/services/claude-hook-service.js +6 -0
- package/dist/backend/services/claude-transcript-service.js +2 -13
- package/dist/backend/services/claude-version-check.js +46 -0
- package/dist/backend/services/gate-review-service.js +47 -8
- package/dist/backend/services/harness-service.js +41 -20
- package/dist/backend/services/message-service.js +30 -6
- package/dist/backend/services/pm-user-question.js +2 -1
- package/dist/backend/services/project-service.js +8 -2
- package/dist/backend/services/runtime-recovery-service.js +36 -9
- package/dist/backend/services/session-service.js +10 -19
- package/dist/backend/services/task-close-service.js +1 -0
- package/dist/backend/services/terminal-process-exit-service.js +4 -1
- package/dist/backend/services/workflow-control-service.js +55 -11
- package/dist/backend/templates/harness/architect-agent.js +2 -1
- package/dist/backend/templates/harness/architect-evidence-worker-agent.js +2 -1
- package/dist/backend/templates/harness/architect-scaffold-worker-agent.js +8 -2
- package/dist/backend/templates/harness/architect-validation-worker-agent.js +2 -1
- package/dist/backend/templates/harness/architect-worker-frontmatter.js +33 -0
- package/dist/backend/templates/harness/check-scaffold-ledger.js +480 -511
- package/dist/backend/templates/harness/coder-worker-agent.js +1 -0
- package/dist/backend/templates/harness/gate-review.js +676 -643
- package/dist/backend/templates/harness/node-tool-runtime.js +102 -0
- package/dist/backend/templates/harness/resolve-durable-doc-assignment.js +49 -55
- package/dist/backend/templates/harness/restart-architect-skill.js +49 -58
- package/dist/backend/templates/harness/vcm-ask-user-skill.js +57 -59
- package/dist/backend/templates/harness/vcm-propose-memory-skill.js +4 -0
- package/dist/backend/templates/harness/vcm-report-harness-issue-skill.js +6 -2
- package/dist/backend/templates/harness/vcm-task-state-skill.js +66 -72
- package/dist/shared/types/app-settings.js +31 -0
- package/dist-frontend/assets/index-CShYYQQa.css +32 -0
- package/dist-frontend/assets/{index-DqANomt1.js → index-DOvvS76Q.js} +41 -41
- package/dist-frontend/index.html +2 -2
- package/package.json +1 -1
- package/scripts/harness-tools/check-durable-docs +332 -298
- package/scripts/harness-tools/generate-module-index +1047 -512
- package/scripts/harness-tools/generate-public-surface +1231 -1069
- package/scripts/harness-tools/package.json +3 -0
- package/scripts/harness-tools/run-long-check +608 -531
- package/scripts/harness-tools/vcm-artifact +181 -113
- package/scripts/harness-tools/vcm-bash-guard +839 -605
- package/scripts/harness-tools/vcm-subagent-guard +67 -63
- package/scripts/harness-tools/watch-job +313 -238
- package/dist-frontend/assets/index-xgiQeUD5.css +0 -32
|
@@ -1,114 +1,182 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
2
|
-
"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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();
|