conductor-harness 1.0.9 → 1.1.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/package.json +1 -1
- package/runtime/.claude/CLAUDE.md.template +4 -6
- package/runtime/install.sh +123 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# [
|
|
1
|
+
# [project-name]
|
|
2
2
|
|
|
3
|
-
> **Stack**: [framework] | [database] | [deployment] | [pkg
|
|
3
|
+
> **Stack**: [framework] | [database] | [deployment] | [pkg-manager]
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -38,15 +38,13 @@
|
|
|
38
38
|
|
|
39
39
|
## MCP Servers
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
| Server | Purpose |
|
|
43
|
-
|--------|---------|
|
|
41
|
+
[mcp-servers-table]
|
|
44
42
|
|
|
45
43
|
---
|
|
46
44
|
|
|
47
45
|
## Key Docs
|
|
48
46
|
|
|
49
|
-
|
|
47
|
+
[key-docs]
|
|
50
48
|
|
|
51
49
|
---
|
|
52
50
|
|
package/runtime/install.sh
CHANGED
|
@@ -158,10 +158,130 @@ print("✓ settings.local.json created")
|
|
|
158
158
|
PYEOF
|
|
159
159
|
fi
|
|
160
160
|
|
|
161
|
-
# ── 10. CLAUDE.md — always overwrite
|
|
161
|
+
# ── 10. CLAUDE.md — always overwrite with auto-detected project context ────────
|
|
162
162
|
CLAUDE_MD="$TARGET_DIR/CLAUDE.md"
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
python3 - "$HARNESS_DIR/.claude/CLAUDE.md.template" "$CLAUDE_MD" "$TARGET_DIR" "$PKG_MANAGER" "$USE_RAILWAY" <<'PYEOF'
|
|
164
|
+
import sys, json, os, re
|
|
165
|
+
|
|
166
|
+
template_path, out_path, cwd, pkg_manager, use_railway = sys.argv[1:]
|
|
167
|
+
|
|
168
|
+
with open(template_path) as f:
|
|
169
|
+
content = f.read()
|
|
170
|
+
|
|
171
|
+
# ── Read package.json ──────────────────────────────────────────────────────────
|
|
172
|
+
pkg = {}
|
|
173
|
+
pkg_path = os.path.join(cwd, "package.json")
|
|
174
|
+
if os.path.exists(pkg_path):
|
|
175
|
+
with open(pkg_path) as f:
|
|
176
|
+
pkg = json.load(f)
|
|
177
|
+
deps = {**pkg.get("dependencies", {}), **pkg.get("devDependencies", {})}
|
|
178
|
+
project_name = pkg.get("name", os.path.basename(cwd))
|
|
179
|
+
|
|
180
|
+
# ── Framework detection ────────────────────────────────────────────────────────
|
|
181
|
+
framework = "unknown"
|
|
182
|
+
if "next" in deps and "payload" in deps:
|
|
183
|
+
framework = "Next.js + Payload CMS"
|
|
184
|
+
elif "next" in deps:
|
|
185
|
+
framework = "Next.js"
|
|
186
|
+
elif "@remix-run/node" in deps or "remix" in deps:
|
|
187
|
+
framework = "Remix"
|
|
188
|
+
elif "nuxt" in deps:
|
|
189
|
+
framework = "Nuxt"
|
|
190
|
+
elif "hono" in deps:
|
|
191
|
+
framework = "Hono"
|
|
192
|
+
elif "fastify" in deps:
|
|
193
|
+
framework = "Fastify"
|
|
194
|
+
elif "express" in deps:
|
|
195
|
+
framework = "Express"
|
|
196
|
+
elif "vite" in deps:
|
|
197
|
+
framework = "Vite"
|
|
198
|
+
|
|
199
|
+
# ── Database detection ─────────────────────────────────────────────────────────
|
|
200
|
+
database = "unknown"
|
|
201
|
+
if "@payloadcms/db-postgres" in deps:
|
|
202
|
+
database = "PostgreSQL (Payload)"
|
|
203
|
+
elif "@payloadcms/db-mongodb" in deps:
|
|
204
|
+
database = "MongoDB (Payload)"
|
|
205
|
+
elif "@prisma/client" in deps or "prisma" in deps:
|
|
206
|
+
database = "PostgreSQL (Prisma)"
|
|
207
|
+
elif "drizzle-orm" in deps:
|
|
208
|
+
database = "PostgreSQL (Drizzle)"
|
|
209
|
+
elif "mongoose" in deps:
|
|
210
|
+
database = "MongoDB"
|
|
211
|
+
elif "better-sqlite3" in deps:
|
|
212
|
+
database = "SQLite"
|
|
213
|
+
elif "pg" in deps or "postgres" in deps:
|
|
214
|
+
database = "PostgreSQL"
|
|
215
|
+
|
|
216
|
+
# ── Deployment detection ───────────────────────────────────────────────────────
|
|
217
|
+
deployment = "unknown"
|
|
218
|
+
if use_railway in ("y", "yes"):
|
|
219
|
+
deployment = "Railway"
|
|
220
|
+
elif os.path.exists(os.path.join(cwd, "vercel.json")) or os.path.exists(os.path.join(cwd, ".vercel")):
|
|
221
|
+
deployment = "Vercel"
|
|
222
|
+
elif os.path.exists(os.path.join(cwd, "fly.toml")):
|
|
223
|
+
deployment = "Fly.io"
|
|
224
|
+
elif os.path.exists(os.path.join(cwd, "netlify.toml")):
|
|
225
|
+
deployment = "Netlify"
|
|
226
|
+
elif os.path.exists(os.path.join(cwd, "Dockerfile")):
|
|
227
|
+
deployment = "Docker"
|
|
228
|
+
|
|
229
|
+
# ── MCP servers ────────────────────────────────────────────────────────────────
|
|
230
|
+
known_purposes = {
|
|
231
|
+
"hindsight": "Cross-session memory (decisions, gotchas, patterns)",
|
|
232
|
+
"linear": "Issue tracking — read/update Linear issues",
|
|
233
|
+
"context7": "Up-to-date framework and package documentation",
|
|
234
|
+
"graphiti-memory": "Graph memory",
|
|
235
|
+
"github": "GitHub repos, PRs, issues",
|
|
236
|
+
"postgres": "Direct database queries",
|
|
237
|
+
"filesystem": "File system access",
|
|
238
|
+
"brave-search": "Web search",
|
|
239
|
+
"puppeteer": "Browser automation",
|
|
240
|
+
}
|
|
241
|
+
mcp_servers = {}
|
|
242
|
+
claude_cfg = os.path.expanduser("~/.claude.json")
|
|
243
|
+
if os.path.exists(claude_cfg):
|
|
244
|
+
with open(claude_cfg) as f:
|
|
245
|
+
mcp_servers.update(json.load(f).get("mcpServers", {}))
|
|
246
|
+
mcp_json = os.path.join(cwd, ".mcp.json")
|
|
247
|
+
if os.path.exists(mcp_json):
|
|
248
|
+
with open(mcp_json) as f:
|
|
249
|
+
mcp_servers.update(json.load(f).get("mcpServers", {}))
|
|
250
|
+
|
|
251
|
+
if mcp_servers:
|
|
252
|
+
rows = ["| Server | Purpose |", "|--------|---------|"]
|
|
253
|
+
for name in sorted(mcp_servers):
|
|
254
|
+
purpose = known_purposes.get(name, "—")
|
|
255
|
+
rows.append(f"| `{name}` | {purpose} |")
|
|
256
|
+
mcp_table = "\n".join(rows)
|
|
257
|
+
else:
|
|
258
|
+
mcp_table = "| Server | Purpose |\n|--------|---------|"
|
|
259
|
+
|
|
260
|
+
# ── Key docs ───────────────────────────────────────────────────────────────────
|
|
261
|
+
doc_candidates = [
|
|
262
|
+
("README.md", "Project overview"),
|
|
263
|
+
("docs/", "Documentation folder"),
|
|
264
|
+
("ARCHITECTURE.md", "Architecture notes"),
|
|
265
|
+
("CONTRIBUTING.md", "Contribution guide"),
|
|
266
|
+
(".env.example", "Environment variables reference"),
|
|
267
|
+
]
|
|
268
|
+
found_docs = [f"- `{path}` — {desc}" for path, desc in doc_candidates
|
|
269
|
+
if os.path.exists(os.path.join(cwd, path))]
|
|
270
|
+
key_docs = "\n".join(found_docs) if found_docs else "<!-- Add: architecture docs, golden rules, README -->"
|
|
271
|
+
|
|
272
|
+
# ── Substitute ────────────────────────────────────────────────────────────────
|
|
273
|
+
content = content.replace("[project-name]", project_name)
|
|
274
|
+
content = content.replace("[framework]", framework)
|
|
275
|
+
content = content.replace("[database]", database)
|
|
276
|
+
content = content.replace("[deployment]", deployment)
|
|
277
|
+
content = content.replace("[pkg-manager]", pkg_manager)
|
|
278
|
+
content = content.replace("[mcp-servers-table]", mcp_table)
|
|
279
|
+
content = content.replace("[key-docs]", key_docs)
|
|
280
|
+
|
|
281
|
+
with open(out_path, "w") as f:
|
|
282
|
+
f.write(content)
|
|
283
|
+
print(f"✓ CLAUDE.md written — {framework} | {database} | {deployment} | {pkg_manager}")
|
|
284
|
+
PYEOF
|
|
165
285
|
|
|
166
286
|
# ── 11. conductor.json — always overwrite ─────────────────────────────────────
|
|
167
287
|
CONDUCTOR_FILE="$TARGET_DIR/conductor.json"
|