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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "conductor-harness",
3
- "version": "1.0.9",
3
+ "version": "1.1.0",
4
4
  "description": "Claude Code harness for Conductor projects — hooks, memory, Linear, and workflow context",
5
5
  "bin": {
6
6
  "conductor-harness": "./bin/conductor-harness.js"
@@ -1,6 +1,6 @@
1
- # [Project Name]
1
+ # [project-name]
2
2
 
3
- > **Stack**: [framework] | [database] | [deployment] | [pkg manager]
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
- <!-- Add project-specific MCP servers here -->
42
- | Server | Purpose |
43
- |--------|---------|
41
+ [mcp-servers-table]
44
42
 
45
43
  ---
46
44
 
47
45
  ## Key Docs
48
46
 
49
- <!-- Add: architecture docs, golden rules, README -->
47
+ [key-docs]
50
48
 
51
49
  ---
52
50
 
@@ -158,10 +158,130 @@ print("✓ settings.local.json created")
158
158
  PYEOF
159
159
  fi
160
160
 
161
- # ── 10. CLAUDE.md — always overwrite, substitute detected pkg manager ─────────
161
+ # ── 10. CLAUDE.md — always overwrite with auto-detected project context ────────
162
162
  CLAUDE_MD="$TARGET_DIR/CLAUDE.md"
163
- sed "s/\[pkg manager\]/$PKG_MANAGER/g" "$HARNESS_DIR/.claude/CLAUDE.md.template" > "$CLAUDE_MD"
164
- echo "✓ CLAUDE.md written (overwritten, pkg manager: $PKG_MANAGER)"
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"