vibe-coding-master 0.0.17 → 0.2.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.
Files changed (42) hide show
  1. package/README.md +57 -28
  2. package/dist/backend/api/artifact-routes.js +5 -5
  3. package/dist/backend/api/harness-routes.js +8 -0
  4. package/dist/backend/server.js +8 -2
  5. package/dist/backend/services/artifact-service.js +12 -12
  6. package/dist/backend/services/harness-service.js +579 -5
  7. package/dist/backend/services/project-service.js +4 -1
  8. package/dist/backend/services/session-service.js +1 -3
  9. package/dist/backend/services/task-service.js +16 -17
  10. package/dist/backend/templates/handoff.js +64 -26
  11. package/dist/backend/templates/harness/architect-agent.js +42 -12
  12. package/dist/backend/templates/harness/claude-root.js +42 -18
  13. package/dist/backend/templates/harness/coder-agent.js +15 -11
  14. package/dist/backend/templates/harness/known-issues-doc.js +22 -0
  15. package/dist/backend/templates/harness/project-manager-agent.js +66 -16
  16. package/dist/backend/templates/harness/pull-request-template.js +29 -0
  17. package/dist/backend/templates/harness/reviewer-agent.js +40 -12
  18. package/dist/backend/templates/harness/vcm-final-acceptance-skill.js +105 -0
  19. package/dist/backend/templates/harness/vcm-harness-bootstrap-skill.js +78 -0
  20. package/dist/backend/templates/harness/vcm-long-running-validation-skill.js +50 -0
  21. package/dist/backend/templates/harness/vcm-route-message-skill.js +86 -0
  22. package/dist/backend/templates/message-envelope.js +1 -0
  23. package/dist/backend/templates/role-command.js +7 -1
  24. package/dist/shared/validation/artifact-check.js +14 -9
  25. package/dist-frontend/assets/index-CrY5Ryps.js +90 -0
  26. package/dist-frontend/assets/index-CvvtrrCN.css +32 -0
  27. package/dist-frontend/index.html +2 -2
  28. package/docs/cc-best-practices.md +433 -192
  29. package/docs/full-harness-baseline.md +254 -0
  30. package/docs/product-design.md +9 -9
  31. package/docs/v0.2-implementation-plan.md +379 -0
  32. package/docs/vcm-cc-best-practices.md +449 -0
  33. package/package.json +3 -1
  34. package/scripts/harness-tools/generate-module-index +298 -0
  35. package/scripts/harness-tools/generate-public-surface +692 -0
  36. package/scripts/install-vcm-harness.mjs +1607 -0
  37. package/scripts/uninstall-vcm-harness.mjs +490 -0
  38. package/scripts/verify-package.mjs +4 -0
  39. package/dist-frontend/assets/index-D40qaonx.css +0 -32
  40. package/dist-frontend/assets/index-DK2F4LFT.js +0 -90
  41. package/docs/v1-architecture-design.md +0 -1014
  42. package/docs/v1-implementation-plan.md +0 -1379
@@ -0,0 +1,298 @@
1
+ #!/usr/bin/env python3
2
+ import argparse
3
+ import fnmatch
4
+ import json
5
+ import subprocess
6
+ import sys
7
+ from pathlib import Path
8
+
9
+ try:
10
+ import tomllib
11
+ except ModuleNotFoundError:
12
+ tomllib = None
13
+
14
+
15
+ def relative_path(path: Path, root: Path) -> str:
16
+ try:
17
+ rel = path.absolute().relative_to(root.absolute())
18
+ except ValueError:
19
+ rel = path.resolve().relative_to(root.resolve())
20
+ return "." if str(rel) == "." else rel.as_posix()
21
+
22
+
23
+ def find_cargo_root(project_root: Path) -> Path:
24
+ if (project_root / "Cargo.toml").is_file():
25
+ return project_root
26
+
27
+ for child in sorted(project_root.iterdir(), key=lambda path: path.name):
28
+ if child.is_dir() and (child / "Cargo.toml").is_file():
29
+ return child
30
+
31
+ raise SystemExit(f"Could not find Cargo.toml in {project_root} or its direct child directories.")
32
+
33
+
34
+ def load_toml(path: Path) -> dict:
35
+ if tomllib is None:
36
+ raise SystemExit("Python 3.11+ is required to parse Cargo.toml files.")
37
+ return tomllib.loads(path.read_text())
38
+
39
+
40
+ def load_cargo_metadata(cargo_root: Path) -> dict | None:
41
+ result = subprocess.run(
42
+ ["cargo", "metadata", "--format-version", "1", "--no-deps"],
43
+ cwd=cargo_root,
44
+ check=False,
45
+ text=True,
46
+ stdout=subprocess.PIPE,
47
+ stderr=subprocess.PIPE,
48
+ )
49
+ if result.returncode != 0:
50
+ return None
51
+ return json.loads(result.stdout)
52
+
53
+
54
+ def path_is_excluded(relative: str, excludes: list[str]) -> bool:
55
+ normalized = relative.rstrip("/")
56
+ for pattern in excludes:
57
+ normalized_pattern = pattern.rstrip("/")
58
+ if (
59
+ normalized == normalized_pattern
60
+ or normalized.startswith(f"{normalized_pattern}/")
61
+ or fnmatch.fnmatch(normalized, normalized_pattern)
62
+ ):
63
+ return True
64
+ return False
65
+
66
+
67
+ def valid_workspace_member_manifests(cargo_root: Path) -> list[Path]:
68
+ data = load_toml(cargo_root / "Cargo.toml")
69
+ workspace = data.get("workspace", {})
70
+ members = workspace.get("members", [])
71
+ excludes = workspace.get("exclude", [])
72
+
73
+ manifests: list[Path] = []
74
+ seen: set[Path] = set()
75
+
76
+ if data.get("package", {}).get("name"):
77
+ manifests.append(cargo_root / "Cargo.toml")
78
+ seen.add(cargo_root / "Cargo.toml")
79
+
80
+ for member in members:
81
+ candidates = sorted(cargo_root.glob(member)) if "*" in member else [cargo_root / member]
82
+ for candidate in candidates:
83
+ if not candidate.is_dir():
84
+ continue
85
+ member_rel = relative_path(candidate, cargo_root)
86
+ if path_is_excluded(member_rel, excludes):
87
+ continue
88
+ manifest = candidate / "Cargo.toml"
89
+ if not manifest.is_file() or manifest in seen:
90
+ continue
91
+ manifests.append(manifest)
92
+ seen.add(manifest)
93
+
94
+ return manifests
95
+
96
+
97
+ def package_name(manifest: Path) -> str | None:
98
+ package = load_toml(manifest).get("package", {})
99
+ name = package.get("name")
100
+ return name if isinstance(name, str) else None
101
+
102
+
103
+ def dependency_names_from_table(table: dict) -> set[str]:
104
+ names: set[str] = set()
105
+ for name, value in table.items():
106
+ if isinstance(value, dict):
107
+ package = value.get("package")
108
+ names.add(package if isinstance(package, str) else name)
109
+ else:
110
+ names.add(name)
111
+ return names
112
+
113
+
114
+ def manifest_dependency_names(manifest: Path) -> set[str]:
115
+ data = load_toml(manifest)
116
+ names: set[str] = set()
117
+ for key in ("dependencies", "dev-dependencies", "build-dependencies"):
118
+ table = data.get(key, {})
119
+ if isinstance(table, dict):
120
+ names.update(dependency_names_from_table(table))
121
+
122
+ target = data.get("target", {})
123
+ if isinstance(target, dict):
124
+ for target_table in target.values():
125
+ if not isinstance(target_table, dict):
126
+ continue
127
+ for key in ("dependencies", "dev-dependencies", "build-dependencies"):
128
+ table = target_table.get(key, {})
129
+ if isinstance(table, dict):
130
+ names.update(dependency_names_from_table(table))
131
+ return names
132
+
133
+
134
+ def infer_layer(module_cargo_path: str, cargo_root: Path, project_root: Path) -> tuple[str, str]:
135
+ if module_cargo_path == ".":
136
+ return ("root", relative_path(cargo_root, project_root))
137
+ first = module_cargo_path.split("/", 1)[0]
138
+ return (first, relative_path(cargo_root / first, project_root))
139
+
140
+
141
+ def rust_files_under(module_dir: Path, project_root: Path, child: str) -> list[str]:
142
+ root = module_dir / child
143
+ if not root.is_dir():
144
+ return []
145
+ return sorted(
146
+ relative_path(path, project_root)
147
+ for path in root.rglob("*.rs")
148
+ if path.is_file()
149
+ )
150
+
151
+
152
+ def package_records_from_metadata(project_root: Path, cargo_root: Path, metadata: dict) -> list[dict]:
153
+ workspace_root = Path(metadata["workspace_root"])
154
+ workspace_member_ids = set(metadata["workspace_members"])
155
+ member_order = {member_id: index for index, member_id in enumerate(metadata["workspace_members"])}
156
+
157
+ packages = [
158
+ package
159
+ for package in metadata["packages"]
160
+ if package["id"] in workspace_member_ids
161
+ ]
162
+ packages.sort(key=lambda package: member_order[package["id"]])
163
+
164
+ workspace_names = {package["name"] for package in packages}
165
+ records = []
166
+ for package in packages:
167
+ dependency_names = {
168
+ dependency["name"]
169
+ for dependency in package.get("dependencies", [])
170
+ if dependency.get("name") in workspace_names
171
+ }
172
+ records.append(
173
+ {
174
+ "name": package["name"],
175
+ "manifest": Path(package["manifest_path"]),
176
+ "workspaceDependencies": sorted(dependency_names),
177
+ }
178
+ )
179
+ return records
180
+
181
+
182
+ def package_records_from_manifests(cargo_root: Path) -> list[dict]:
183
+ manifests = valid_workspace_member_manifests(cargo_root)
184
+ names_by_manifest = {
185
+ manifest: name
186
+ for manifest in manifests
187
+ if (name := package_name(manifest)) is not None
188
+ }
189
+ workspace_names = set(names_by_manifest.values())
190
+ records = []
191
+
192
+ for manifest, name in names_by_manifest.items():
193
+ dependency_names = manifest_dependency_names(manifest) & workspace_names
194
+ records.append(
195
+ {
196
+ "name": name,
197
+ "manifest": manifest,
198
+ "workspaceDependencies": sorted(dependency_names),
199
+ }
200
+ )
201
+ return records
202
+
203
+
204
+ def build_index(project_root: Path) -> dict:
205
+ cargo_root = find_cargo_root(project_root)
206
+ metadata = load_cargo_metadata(cargo_root)
207
+ records = (
208
+ package_records_from_metadata(project_root, cargo_root, metadata)
209
+ if metadata is not None
210
+ else package_records_from_manifests(cargo_root)
211
+ )
212
+
213
+ layers: list[dict] = []
214
+ layer_by_name: dict[str, dict] = {}
215
+
216
+ for record in records:
217
+ manifest_path = record["manifest"]
218
+ module_dir = manifest_path.parent
219
+ module_path = relative_path(module_dir, project_root)
220
+ manifest_rel = relative_path(manifest_path, project_root)
221
+ module_cargo_path = relative_path(module_dir, cargo_root)
222
+ layer_name, layer_path = infer_layer(module_cargo_path, cargo_root, project_root)
223
+
224
+ if layer_name not in layer_by_name:
225
+ layer = {
226
+ "name": layer_name,
227
+ "path": layer_path,
228
+ "modules": [],
229
+ }
230
+ layer_by_name[layer_name] = layer
231
+ layers.append(layer)
232
+
233
+ layer_by_name[layer_name]["modules"].append(
234
+ {
235
+ "name": record["name"],
236
+ "path": module_path,
237
+ "manifest": manifest_rel,
238
+ "architectureDoc": f"{module_path}/ARCHITECTURE.md"
239
+ if module_path != "."
240
+ else "ARCHITECTURE.md",
241
+ "workspaceDependencies": record["workspaceDependencies"],
242
+ "files": {
243
+ "source": rust_files_under(module_dir, project_root, "src"),
244
+ "tests": rust_files_under(module_dir, project_root, "tests"),
245
+ },
246
+ }
247
+ )
248
+
249
+ return {
250
+ "schemaVersion": 1,
251
+ "kind": "module-index",
252
+ "generatedBy": ".ai/tools/generate-module-index",
253
+ "workspace": {
254
+ "root": relative_path(cargo_root, project_root),
255
+ "manifest": relative_path(cargo_root / "Cargo.toml", project_root),
256
+ },
257
+ "layerInference": {
258
+ "method": "path-first-segment-from-cargo-root",
259
+ "rootPackageLayer": "root",
260
+ },
261
+ "layers": layers,
262
+ }
263
+
264
+
265
+ def main() -> int:
266
+ parser = argparse.ArgumentParser(description="Generate .ai/generated/module-index.json from cargo metadata.")
267
+ parser.add_argument("--check", action="store_true", help="Fail if the generated module index differs from the current file.")
268
+ parser.add_argument("--print", action="store_true", help="Print generated JSON instead of writing it.")
269
+ parser.add_argument("--output", default=".ai/generated/module-index.json", help="Output path relative to the project root.")
270
+ args = parser.parse_args()
271
+
272
+ root = Path(__file__).resolve().parents[2]
273
+ generated = json.dumps(build_index(root), indent=2, sort_keys=False) + "\n"
274
+ output_path = root / args.output
275
+
276
+ if args.check:
277
+ if not output_path.is_file():
278
+ sys.stderr.write(f"Missing generated module index: {output_path.relative_to(root)}\n")
279
+ return 1
280
+ current = output_path.read_text()
281
+ if current != generated:
282
+ sys.stderr.write(f"Stale generated module index: {output_path.relative_to(root)}\n")
283
+ return 1
284
+ print("generate-module-index check passed")
285
+ return 0
286
+
287
+ if args.print:
288
+ sys.stdout.write(generated)
289
+ return 0
290
+
291
+ output_path.parent.mkdir(parents=True, exist_ok=True)
292
+ output_path.write_text(generated)
293
+ print(f"wrote {output_path.relative_to(root)}")
294
+ return 0
295
+
296
+
297
+ if __name__ == "__main__":
298
+ raise SystemExit(main())