dark-factory 0.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/README.md ADDED
@@ -0,0 +1,276 @@
1
+ # Dark Factory
2
+
3
+ **Specs in, production-grade features out.**
4
+
5
+ Dark Factory is an open-source multi-agent framework for Claude Code. Feed it a raw idea or a bug report — it assembles a team of AI specialists (BA, principal engineer, developer, QA) who research, challenge, implement, and validate autonomously. No agent can cut corners because no agent has the full picture.
6
+
7
+ > Inspired by [The Dark Factory Pattern](https://hackernoon.com/the-dark-factory-pattern-moving-from-ai-assisted-to-fully-autonomous-coding) — moving from AI-assisted to fully autonomous coding.
8
+
9
+ ```
10
+ ┌─────────────┐
11
+ /df-onboard ──────▶│ Onboard │──▶ project-profile.md
12
+ └─────────────┘
13
+ ┌─────────────┐ ┌───────────────┐
14
+ /df-intake ──────▶│ Spec Agent │────▶│ Architect │──▶ APPROVED
15
+ │ (BA) │◀────│ (Principal) │ │
16
+ └─────────────┘ 3+ │ 3+ rounds │ │
17
+ rounds └──────────────┘ ▼
18
+ ┌─────────────┐ ┌─────────────┐ ┌──────────┐
19
+ │ Code Agent │────▶│ Test Agent │──▶│ Promote │──▶ Archive
20
+ │ (Dev) │◀────│ (QA) │ │ + Archive│
21
+ └─────────────┘ max└─────────────┘ └──────────┘
22
+ 3 rounds
23
+ ```
24
+
25
+ ---
26
+
27
+ ## Quick Start
28
+
29
+ **Prerequisites**: [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed + Node.js 18+
30
+
31
+ ```bash
32
+ npx dark-factory init
33
+ ```
34
+
35
+ Then open Claude Code and run `/df-onboard` to map your project.
36
+
37
+ To update to the latest version later:
38
+
39
+ ```bash
40
+ npx dark-factory update
41
+ ```
42
+
43
+ ---
44
+
45
+ ## Usage
46
+
47
+ ### 1. Onboard your project (once)
48
+
49
+ ```
50
+ /df-onboard
51
+ ```
52
+
53
+ Maps your tech stack, architecture, conventions, and quality bar into `dark-factory/project-profile.md`. Every agent reads this before starting work.
54
+
55
+ ### 2. Add a feature
56
+
57
+ ```
58
+ /df-intake I need an API endpoint that lets users export their data as CSV
59
+ ```
60
+
61
+ 1. **Spec-agent** researches the codebase, asks focused questions, proposes scope (IN/OUT), writes spec + scenarios
62
+ 2. You review holdout scenarios in `dark-factory/scenarios/holdout/`
63
+ 3. `/df-orchestrate user-csv-export` — architect reviews (3+ rounds), code-agent implements, test-agent validates
64
+ 4. On success: holdout tests promoted into your permanent test suite, artifacts archived
65
+
66
+ ### 3. Fix a bug
67
+
68
+ ```
69
+ /df-debug Users get 500 errors when exporting CSV with special characters in the filename
70
+ ```
71
+
72
+ 1. **Debug-agent** traces root cause (not just the symptom), maps impact, writes debug report
73
+ 2. You confirm the diagnosis
74
+ 3. `/df-orchestrate csv-special-chars-fix` — architect reviews, then strict red-green cycle:
75
+ - Write a failing test that **proves** the bug (no source code changes)
76
+ - Implement the minimal fix (no test changes)
77
+ - Failing test now passes, all existing tests still pass
78
+ 4. Holdout validation, promote, archive
79
+
80
+ ### 4. Maintenance
81
+
82
+ ```
83
+ /df-cleanup
84
+ ```
85
+
86
+ Retries stuck promotions, completes archival, lists stale features.
87
+
88
+ ---
89
+
90
+ ## Why Dark Factory?
91
+
92
+ AI coding assistants write code fast, but fast code on a flawed spec is fast failure. They skip architecture review, miss security concerns, and can't validate their own work honestly — they wrote both the code and the tests.
93
+
94
+ Dark Factory separates concerns into independent agents with strict information barriers:
95
+
96
+ | What goes wrong without it | How Dark Factory prevents it |
97
+ |---|---|
98
+ | AI guesses the scope instead of asking | Spec-agent runs structured discovery — asks focused questions, proposes IN/OUT scope, waits for confirmation |
99
+ | AI skips architecture review | Architect-agent reviews every spec for security, performance, data integrity — 3+ rounds before any code |
100
+ | AI writes tests that match its own implementation | Test-agent uses **holdout scenarios** the code-agent has never seen — can't teach to the test |
101
+ | Bug fixes that mask symptoms | Debug-agent traces root cause forensically; code-agent must write a failing test FIRST, then fix WITHOUT changing the test |
102
+ | AI doesn't understand the existing codebase | Onboard-agent maps architecture, conventions, and quality bar before any work begins |
103
+ | Specs and test artifacts pile up forever | Auto-promote holdout tests into permanent suite, then archive artifacts |
104
+
105
+ ---
106
+
107
+ ## How It Works
108
+
109
+ ### The 7 Agents
110
+
111
+ | Agent | Role | Analogy |
112
+ |-------|------|---------|
113
+ | **Onboard** | Maps the project before any work begins | New team lead's first week |
114
+ | **Spec** | Discovers scope, challenges assumptions, writes specs | Senior BA who asks hard questions |
115
+ | **Debug** | Forensic root cause analysis, impact assessment | The engineer who reads stack traces for breakfast |
116
+ | **Architect** | Reviews specs for architecture, security, performance | Principal engineer who blocks bad designs |
117
+ | **Code** | Implements features and fixes | Senior dev who follows the spec exactly |
118
+ | **Test** | Validates with hidden scenarios | QA who writes tests the dev has never seen |
119
+ | **Promote** | Moves holdout tests into permanent test suite | Release engineer |
120
+
121
+ ### Information Barriers
122
+
123
+ The key innovation. Each agent has **strict boundaries** on what it can see:
124
+
125
+ ```
126
+ ┌─────────────────────────────────────────────┐
127
+ │ Project Profile │
128
+ │ (all agents except test/promote can read) │
129
+ └─────────────────────────────────────────────┘
130
+
131
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
132
+ │ Spec │ │ Code │ │ Test │
133
+ │ Agent │ │ Agent │ │ Agent │
134
+ │ │ │ │ │ │
135
+ │ Sees: │ │ Sees: │ │ Sees: │
136
+ │ codebase │ │ spec, │ │ spec, │
137
+ │ docs │ │ PUBLIC │ │ HOLDOUT │
138
+ │ │ │ scenarios│ │ scenarios│
139
+ │ Cannot: │ │ │ │ │
140
+ │ holdout │ │ Cannot: │ │ Cannot: │
141
+ │ results │ │ HOLDOUT │ │ PUBLIC │
142
+ └──────────┘ │ results │ │ scenarios│
143
+ └──────────┘ └──────────┘
144
+
145
+ ┌──────────┐
146
+ │Architect │ Can see: spec, codebase, project profile
147
+ │ Agent │ CANNOT see: ANY scenarios (public or holdout)
148
+ │ │ CANNOT discuss tests with other agents
149
+ └──────────┘
150
+ ```
151
+
152
+ The code-agent can't "teach to the test" because it never sees the holdout scenarios. The architect can't compromise test coverage because it never sees tests at all. The test-agent can't soften its validation because it doesn't know what the code-agent was told to build.
153
+
154
+ ### Red-Green Cycle (Bugfixes)
155
+
156
+ Dark Factory enforces strict discipline that prevents the most common AI failure mode: fixing the symptom instead of the root cause.
157
+
158
+ ```
159
+ Phase 1 (Red): Write test → Test FAILS ✓ (bug is real)
160
+ ⚠ Zero source code changes allowed
161
+
162
+ Phase 2 (Green): Implement fix → Test PASSES ✓ (fix works)
163
+ ⚠ Zero test file changes allowed
164
+ ⚠ All existing tests must still pass
165
+ ```
166
+
167
+ If the test doesn't fail in Phase 1, the test is wrong — not the bug. If existing tests break in Phase 2, the fix has regression — revise the fix, not the tests.
168
+
169
+ ### Feature Lifecycle
170
+
171
+ Every feature is tracked in `dark-factory/manifest.json`:
172
+
173
+ ```
174
+ active → passed → promoted → archived
175
+ │ │ │ │
176
+ │ │ │ └── Specs + scenarios in dark-factory/archive/
177
+ │ │ └── Holdout tests in permanent test suite
178
+ │ └── All holdout tests passed
179
+ └── Spec created, awaiting implementation
180
+ ```
181
+
182
+ `/df-cleanup` recovers features stuck in intermediate states.
183
+
184
+ ---
185
+
186
+ ## Reference
187
+
188
+ ### Commands
189
+
190
+ | Command | What it does |
191
+ |---------|-------------|
192
+ | `/df-onboard` | Map project architecture, conventions, quality bar |
193
+ | `/df-intake {desc}` | Create feature spec (discovers scope, writes scenarios) |
194
+ | `/df-debug {desc}` | Investigate bug (root cause, impact, debug report) |
195
+ | `/df-orchestrate {name}` | Implement (architect review → code → test → promote → archive) |
196
+ | `/df-cleanup` | Recover stuck features, list stale work |
197
+ | `/df-spec` | Show spec templates for manual writing |
198
+ | `/df-scenario` | Show scenario templates for manual writing |
199
+
200
+ ### Project Structure
201
+
202
+ ```
203
+ your-project/
204
+ ├── .claude/
205
+ │ ├── agents/ # 7 agent definitions
206
+ │ │ ├── onboard-agent.md
207
+ │ │ ├── spec-agent.md
208
+ │ │ ├── debug-agent.md
209
+ │ │ ├── architect-agent.md
210
+ │ │ ├── code-agent.md
211
+ │ │ ├── test-agent.md
212
+ │ │ └── promote-agent.md
213
+ │ └── skills/ # 7 slash commands
214
+ │ ├── df-onboard/SKILL.md
215
+ │ ├── df-intake/SKILL.md
216
+ │ ├── df-debug/SKILL.md
217
+ │ ├── df-orchestrate/SKILL.md
218
+ │ ├── df-spec/SKILL.md
219
+ │ ├── df-scenario/SKILL.md
220
+ │ └── df-cleanup/SKILL.md
221
+ ├── dark-factory/
222
+ │ ├── project-profile.md # Project map (from /df-onboard)
223
+ │ ├── manifest.json # Feature lifecycle tracking
224
+ │ ├── specs/features/ # Feature specs
225
+ │ ├── specs/bugfixes/ # Debug reports
226
+ │ ├── scenarios/public/ # Visible to code-agent
227
+ │ ├── scenarios/holdout/ # Hidden from code-agent
228
+ │ ├── results/ # Test output (gitignored)
229
+ │ └── archive/ # Completed feature artifacts
230
+ └── CLAUDE.md # Project instructions (auto-updated)
231
+ ```
232
+
233
+ ### Configuration
234
+
235
+ The init script auto-detects your project type:
236
+
237
+ ```bash
238
+ # Force a project type
239
+ node scripts/init-dark-factory.js --dir . --project-type nestjs
240
+ node scripts/init-dark-factory.js --dir . --project-type node
241
+ node scripts/init-dark-factory.js --dir . --project-type generic
242
+
243
+ # Scaffold a first feature
244
+ node scripts/init-dark-factory.js --dir . --feature user-auth
245
+ ```
246
+
247
+ Supported project types affect agent prompts (e.g., NestJS agents know about modules, decorators, and DTOs).
248
+
249
+ ---
250
+
251
+ ## Design Decisions
252
+
253
+ **Why holdout scenarios?** — Without them, the AI writes code and tests from the same understanding. Holdout scenarios are written by the spec-agent (who understands the requirements) and validated by the test-agent (who never talks to the code-agent). The code-agent must implement correctly to pass tests it's never seen.
254
+
255
+ **Why architect review?** — A spec written by a BA may miss performance concerns, security gaps, or architectural inconsistencies. The architect-agent reviews every spec with principal-engineer rigor — but is banned from seeing tests, so it can't influence what gets tested.
256
+
257
+ **Why strict red-green for bugs?** — The most dangerous AI bug fix is one that makes the test pass by changing the test. Dark Factory enforces: write the test first (Phase 1, no code changes allowed), then fix the code (Phase 2, no test changes allowed). If the test doesn't fail, the test is wrong.
258
+
259
+ **Why project onboarding?** — An AI dropped into an unknown codebase will follow "best practices" instead of "this project's practices." The onboard-agent maps reality — messy or clean — so every agent works WITH the existing patterns instead of against them.
260
+
261
+ **Why auto-promote and archive?** — Dark Factory artifacts (specs, scenarios) accumulate forever. After holdout tests pass, they're automatically promoted into the permanent test suite (preserving regression coverage) and artifacts are archived.
262
+
263
+ ---
264
+
265
+ ## Contributing
266
+
267
+ Contributions welcome. The test suite is the source of truth — if the tests pass, the pipeline is intact.
268
+
269
+ ```bash
270
+ # Run all tests (no dependencies — uses Node.js built-in test runner)
271
+ node --test tests/dark-factory-setup.test.js
272
+ ```
273
+
274
+ ## License
275
+
276
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,284 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Dark Factory CLI
5
+ *
6
+ * Usage:
7
+ * npx dark-factory init Install Dark Factory into current project
8
+ * npx dark-factory update Update agents/skills/rules to latest version
9
+ * npx dark-factory init --dir /path/to/project
10
+ */
11
+
12
+ const fs = require("fs");
13
+ const path = require("path");
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Helpers
17
+ // ---------------------------------------------------------------------------
18
+
19
+ const RESET = "\x1b[0m";
20
+ const BOLD = "\x1b[1m";
21
+ const DIM = "\x1b[2m";
22
+ const GREEN = "\x1b[32m";
23
+ const YELLOW = "\x1b[33m";
24
+ const CYAN = "\x1b[36m";
25
+
26
+ function log(msg) { console.log(msg); }
27
+ function info(msg) { console.log(` ${GREEN}+${RESET} ${msg}`); }
28
+ function update(msg) { console.log(` ${YELLOW}~${RESET} ${msg}`); }
29
+ function skip(msg) { console.log(` ${DIM}-${RESET} ${DIM}${msg}${RESET}`); }
30
+
31
+ function ensureDir(dirPath) {
32
+ if (!fs.existsSync(dirPath)) {
33
+ fs.mkdirSync(dirPath, { recursive: true });
34
+ return true;
35
+ }
36
+ return false;
37
+ }
38
+
39
+ function touchGitkeep(dirPath) {
40
+ ensureDir(dirPath);
41
+ const keepPath = path.join(dirPath, ".gitkeep");
42
+ if (!fs.existsSync(keepPath)) {
43
+ fs.writeFileSync(keepPath, "", "utf8");
44
+ }
45
+ }
46
+
47
+ function copyFileWithLog(src, dest) {
48
+ const rel = path.relative(process.cwd(), dest);
49
+ ensureDir(path.dirname(dest));
50
+
51
+ if (fs.existsSync(dest)) {
52
+ const existing = fs.readFileSync(dest, "utf8");
53
+ const incoming = fs.readFileSync(src, "utf8");
54
+ if (existing === incoming) {
55
+ skip(`${rel} (unchanged)`);
56
+ return;
57
+ }
58
+ update(rel);
59
+ } else {
60
+ info(rel);
61
+ }
62
+
63
+ fs.copyFileSync(src, dest);
64
+ }
65
+
66
+ function copyDirRecursive(src, dest) {
67
+ const entries = fs.readdirSync(src, { withFileTypes: true });
68
+ for (const entry of entries) {
69
+ const srcPath = path.join(src, entry.name);
70
+ const destPath = path.join(dest, entry.name);
71
+ if (entry.isDirectory()) {
72
+ copyDirRecursive(srcPath, destPath);
73
+ } else {
74
+ copyFileWithLog(srcPath, destPath);
75
+ }
76
+ }
77
+ }
78
+
79
+ // ---------------------------------------------------------------------------
80
+ // .gitignore management
81
+ // ---------------------------------------------------------------------------
82
+
83
+ function updateGitignore(dir) {
84
+ const gitignorePath = path.join(dir, ".gitignore");
85
+ let content = "";
86
+ if (fs.existsSync(gitignorePath)) {
87
+ content = fs.readFileSync(gitignorePath, "utf8");
88
+ }
89
+
90
+ let modified = false;
91
+
92
+ // .claude selective tracking
93
+ const claudeEntries = [
94
+ "/.claude/*",
95
+ "!/.claude/agents/",
96
+ "!/.claude/rules/",
97
+ "!/.claude/skills/",
98
+ ];
99
+
100
+ const claudeLineRegex = /^[/#]*\s*\.?\/?\.claude\s*$/m;
101
+ if (claudeLineRegex.test(content)) {
102
+ content = content.replace(claudeLineRegex, claudeEntries.join("\n"));
103
+ modified = true;
104
+ } else if (!content.includes("/.claude/*")) {
105
+ content += "\n# Claude Code — selectively track agents, rules, and skills\n" + claudeEntries.join("\n") + "\n";
106
+ modified = true;
107
+ }
108
+
109
+ // Ensure !/.claude/rules/ is present (may be missing from older installs)
110
+ if (content.includes("/.claude/*") && !content.includes("!/.claude/rules/")) {
111
+ content = content.replace("!/.claude/skills/", "!/.claude/rules/\n!/.claude/skills/");
112
+ modified = true;
113
+ }
114
+
115
+ // dark-factory/results
116
+ if (!content.includes("dark-factory/results")) {
117
+ content += "\n# Dark Factory results (local test output)\ndark-factory/results/\n";
118
+ modified = true;
119
+ }
120
+
121
+ if (modified) {
122
+ fs.writeFileSync(gitignorePath, content, "utf8");
123
+ update(".gitignore");
124
+ } else {
125
+ skip(".gitignore (already configured)");
126
+ }
127
+ }
128
+
129
+ // ---------------------------------------------------------------------------
130
+ // Commands
131
+ // ---------------------------------------------------------------------------
132
+
133
+ function cmdInit(targetDir, opts = {}) {
134
+ const templateDir = path.join(__dirname, "..", "template");
135
+
136
+ log("");
137
+ log(`${BOLD}Dark Factory${RESET} — installing into ${CYAN}${targetDir}${RESET}`);
138
+ log("");
139
+
140
+ // 1. Copy .claude/ (agents, skills, rules) — always overwrite to latest
141
+ log(`${BOLD}Agents & Skills${RESET}`);
142
+ copyDirRecursive(
143
+ path.join(templateDir, ".claude"),
144
+ path.join(targetDir, ".claude"),
145
+ );
146
+
147
+ // 2. Create dark-factory/ working directories — never overwrite existing content
148
+ log("");
149
+ log(`${BOLD}Working directories${RESET}`);
150
+ const dfDir = path.join(targetDir, "dark-factory");
151
+ const dirs = [
152
+ "specs/features",
153
+ "specs/bugfixes",
154
+ "scenarios/public",
155
+ "scenarios/holdout",
156
+ "results",
157
+ "archive",
158
+ ];
159
+ for (const d of dirs) {
160
+ const full = path.join(dfDir, d);
161
+ if (ensureDir(full)) {
162
+ info(`dark-factory/${d}/`);
163
+ } else {
164
+ skip(`dark-factory/${d}/ (exists)`);
165
+ }
166
+ touchGitkeep(full);
167
+ }
168
+
169
+ // 3. Create manifest.json if missing
170
+ const manifestPath = path.join(dfDir, "manifest.json");
171
+ if (!fs.existsSync(manifestPath)) {
172
+ fs.writeFileSync(manifestPath, JSON.stringify({ version: 1, features: {} }, null, 2) + "\n", "utf8");
173
+ info("dark-factory/manifest.json");
174
+ } else {
175
+ skip("dark-factory/manifest.json (exists)");
176
+ }
177
+
178
+ // 4. Update .gitignore
179
+ log("");
180
+ log(`${BOLD}Git config${RESET}`);
181
+ updateGitignore(targetDir);
182
+
183
+ // Done
184
+ log("");
185
+ log(`${GREEN}${BOLD}Done!${RESET} Dark Factory is ready.`);
186
+ log("");
187
+ log(`${BOLD}Next steps:${RESET}`);
188
+ log(` 1. Run ${CYAN}/df-onboard${RESET} in Claude Code to map your project`);
189
+ log(` 2. Describe a feature or bug — Dark Factory activates automatically`);
190
+ log(` 3. Or use ${CYAN}/df {description}${RESET} explicitly`);
191
+ log("");
192
+ }
193
+
194
+ function cmdUpdate(targetDir) {
195
+ const templateDir = path.join(__dirname, "..", "template");
196
+
197
+ log("");
198
+ log(`${BOLD}Dark Factory${RESET} — updating agents, skills & rules in ${CYAN}${targetDir}${RESET}`);
199
+ log("");
200
+
201
+ log(`${BOLD}Agents & Skills${RESET}`);
202
+ copyDirRecursive(
203
+ path.join(templateDir, ".claude"),
204
+ path.join(targetDir, ".claude"),
205
+ );
206
+
207
+ // Also update .gitignore in case new entries were added
208
+ log("");
209
+ log(`${BOLD}Git config${RESET}`);
210
+ updateGitignore(targetDir);
211
+
212
+ log("");
213
+ log(`${GREEN}${BOLD}Updated!${RESET} Agents, skills, and rules are now at the latest version.`);
214
+ log(` Your specs, scenarios, and manifest were not touched.`);
215
+ log("");
216
+ }
217
+
218
+ function cmdHelp() {
219
+ log(`
220
+ ${BOLD}Dark Factory${RESET} — AI-powered development pipeline for Claude Code
221
+
222
+ ${BOLD}Usage:${RESET}
223
+ npx dark-factory init Install into current project
224
+ npx dark-factory update Update agents/skills/rules to latest
225
+ npx dark-factory help Show this help
226
+
227
+ ${BOLD}Options:${RESET}
228
+ --dir <path> Target directory (default: current dir)
229
+
230
+ ${BOLD}What gets installed:${RESET}
231
+ .claude/agents/ 7 specialized AI agents
232
+ .claude/skills/ 8 slash command skills (/df, /df-intake, etc.)
233
+ .claude/rules/ Auto-detection rules
234
+ dark-factory/ Working directory (specs, scenarios, results)
235
+
236
+ ${BOLD}After install:${RESET}
237
+ 1. Open Claude Code in your project
238
+ 2. Run /df-onboard to map your project
239
+ 3. Just describe what you need — Dark Factory activates automatically
240
+ `);
241
+ }
242
+
243
+ // ---------------------------------------------------------------------------
244
+ // Main
245
+ // ---------------------------------------------------------------------------
246
+
247
+ function main() {
248
+ const args = process.argv.slice(2);
249
+ let command = null;
250
+ let targetDir = process.cwd();
251
+
252
+ for (let i = 0; i < args.length; i++) {
253
+ if (args[i] === "--dir" && args[i + 1]) {
254
+ targetDir = path.resolve(args[++i]);
255
+ } else if (args[i] === "--help" || args[i] === "-h") {
256
+ command = "help";
257
+ } else if (!args[i].startsWith("-")) {
258
+ command = args[i];
259
+ }
260
+ }
261
+
262
+ switch (command) {
263
+ case "init":
264
+ cmdInit(targetDir);
265
+ break;
266
+ case "update":
267
+ cmdUpdate(targetDir);
268
+ break;
269
+ case "help":
270
+ cmdHelp();
271
+ break;
272
+ default:
273
+ // No command = init (most common use case)
274
+ if (!command) {
275
+ cmdInit(targetDir);
276
+ } else {
277
+ log(`Unknown command: ${command}`);
278
+ log(`Run 'npx dark-factory help' for usage.`);
279
+ process.exit(1);
280
+ }
281
+ }
282
+ }
283
+
284
+ main();
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "dark-factory",
3
+ "version": "0.1.0",
4
+ "description": "AI-powered development pipeline for Claude Code — specs in, production-grade features out",
5
+ "bin": {
6
+ "dark-factory": "bin/cli.js"
7
+ },
8
+ "files": [
9
+ "bin/",
10
+ "template/"
11
+ ],
12
+ "keywords": [
13
+ "claude",
14
+ "claude-code",
15
+ "ai",
16
+ "development",
17
+ "pipeline",
18
+ "agents",
19
+ "spec",
20
+ "testing"
21
+ ],
22
+ "author": "",
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/nguyenhuynhkhanh/dark-factory.git"
27
+ }
28
+ }