joycraft 0.5.20 → 0.6.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 +51 -2
- package/dist/{chunk-VDQTLM2D.js → chunk-4ZI7B4IW.js} +18 -2
- package/dist/chunk-4ZI7B4IW.js.map +1 -0
- package/dist/{chunk-MEPNNJIE.js → chunk-QDRX3WM6.js} +18 -15
- package/dist/chunk-QDRX3WM6.js.map +1 -0
- package/dist/cli.js +3 -3
- package/dist/{init-BWD6IL5I.js → init-GELY5GE2.js} +66 -71
- package/dist/init-GELY5GE2.js.map +1 -0
- package/dist/{init-autofix-EDLJXYFR.js → init-autofix-AA4GDSBZ.js} +2 -2
- package/dist/upgrade-ENNS6HSP.js +414 -0
- package/dist/upgrade-ENNS6HSP.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-MEPNNJIE.js.map +0 -1
- package/dist/chunk-VDQTLM2D.js.map +0 -1
- package/dist/init-BWD6IL5I.js.map +0 -1
- package/dist/upgrade-B6HOE7M3.js +0 -205
- package/dist/upgrade-B6HOE7M3.js.map +0 -1
- /package/dist/{init-autofix-EDLJXYFR.js.map → init-autofix-AA4GDSBZ.js.map} +0 -0
package/README.md
CHANGED
|
@@ -52,8 +52,8 @@ Joycraft auto-detects your tech stack and creates:
|
|
|
52
52
|
|
|
53
53
|
- **CLAUDE.md** with behavioral boundaries (Always / Ask First / Never) and correct build/test/lint commands
|
|
54
54
|
- **AGENTS.md** for Codex compatibility
|
|
55
|
-
- **
|
|
56
|
-
- **docs/** structure: `
|
|
55
|
+
- **15 skills** installed to `.claude/skills/` (Claude Code) and `.agents/skills/` (Codex) — see [Which skill do I need?](#which-skill-do-i-need) below
|
|
56
|
+
- **docs/** structure: `docs/context/` is created up front; feature work lands in `docs/features/<slug>/{brief.md, research.md, design.md, specs/}` and deferred work in `docs/backlog/` — these are created lazily by the skills that write to them
|
|
57
57
|
- **Context documents** in `docs/context/`: production map, dangerous assumptions, decision log, institutional knowledge, and troubleshooting guide
|
|
58
58
|
- **Templates** including atomic spec, feature brief, implementation plan, boundary framework, and workflow templates for scenario generation and autofix loops
|
|
59
59
|
|
|
@@ -78,6 +78,7 @@ Frameworks auto-detected: Next.js, FastAPI, Django, Flask, Actix, Axum, Express,
|
|
|
78
78
|
| Implement a spec with TDD | `/joycraft-implement` | Read spec → write failing tests → implement until green |
|
|
79
79
|
| Run specs autonomously without hand-holding | `/joycraft-implement-level5` | Autofix loop + holdout scenario testing |
|
|
80
80
|
| Verify an implementation independently | `/joycraft-verify` | Read-only subagent checks work against the spec |
|
|
81
|
+
| Set up Joycraft for a team | `/joycraft-collaborative-setup` | Scaffold `docs/areas/`, owner conventions, a team CONTRIBUTING doc |
|
|
81
82
|
|
|
82
83
|
The core loop:
|
|
83
84
|
|
|
@@ -166,6 +167,54 @@ Joycraft synthesizes ideas and patterns from people doing extraordinary work in
|
|
|
166
167
|
- **[Simon Willison](https://x.com/simonw)** for his [analysis of the Software Factory](https://simonwillison.net/2026/Feb/7/software-factory/) that helped contextualize StrongDM's approach for the broader community
|
|
167
168
|
- **[Anthropic](https://www.anthropic.com/)** for Claude Code's skills, hooks, and CLAUDE.md system that makes tool-native AI development possible, and the [harness patterns for long-running agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents)
|
|
168
169
|
|
|
170
|
+
## Migration: Flat → Per-Feature Layout (v0.6+)
|
|
171
|
+
|
|
172
|
+
Starting in v0.6, Joycraft organizes feature artifacts into per-feature folders:
|
|
173
|
+
|
|
174
|
+
- `docs/briefs/<slug>.md` → `docs/features/<slug>/brief.md`
|
|
175
|
+
- `docs/research/<slug>.md` → `docs/features/<slug>/research.md`
|
|
176
|
+
- `docs/designs/<slug>.md` → `docs/features/<slug>/design.md`
|
|
177
|
+
- `docs/specs/<feature>/` → `docs/features/<slug>/specs/` (when `<feature>` matches a brief slug)
|
|
178
|
+
|
|
179
|
+
`npx joycraft upgrade` performs this migration automatically and forcefully on the first
|
|
180
|
+
post-upgrade run — no Y/N prompt. The CLI prints a summary of every move before applying it.
|
|
181
|
+
Spec directories under `docs/specs/` whose name doesn't match any brief slug (area-level specs
|
|
182
|
+
like bugfix folders) are left in place.
|
|
183
|
+
|
|
184
|
+
### What you'll see on the first post-upgrade run
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
Joycraft is migrating your docs/ to the new per-feature layout:
|
|
188
|
+
|
|
189
|
+
2026-04-01-auth-redesign/
|
|
190
|
+
docs/briefs/2026-04-01-auth-redesign.md → docs/features/2026-04-01-auth-redesign/brief.md
|
|
191
|
+
docs/research/2026-04-01-auth-redesign.md → docs/features/2026-04-01-auth-redesign/research.md
|
|
192
|
+
|
|
193
|
+
Left in place — area-level specs (e.g., bugfix areas):
|
|
194
|
+
docs/specs/login-bugfix/
|
|
195
|
+
|
|
196
|
+
Migration complete. See the README section "Migration: Flat → Per-Feature Layout"
|
|
197
|
+
for context on what changed and why. If your project is a git repo, run
|
|
198
|
+
`git status` to inspect the moves before committing.
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Why forced (not opt-in)
|
|
202
|
+
|
|
203
|
+
All doc-producing skills (`joycraft-new-feature`, `joycraft-research`, `joycraft-design`,
|
|
204
|
+
`joycraft-decompose`, etc.) write to the new per-feature paths. Supporting both layouts
|
|
205
|
+
indefinitely would mean every skill carries dual-path branches; the forced migration keeps
|
|
206
|
+
the convention single and skills small.
|
|
207
|
+
|
|
208
|
+
### Recovering / customizing
|
|
209
|
+
|
|
210
|
+
Every move is a plain filesystem move (no `git mv`). If you want a different organization
|
|
211
|
+
after the migration, you can `git mv` files anywhere — Joycraft only depends on the
|
|
212
|
+
`docs/features/<slug>/` shape for skills it ships, not on every doc living there. Git
|
|
213
|
+
history follows files via `git log --follow`.
|
|
214
|
+
|
|
215
|
+
If a brief and its destination already exist (re-running upgrade after a partial migration),
|
|
216
|
+
the move is skipped and reported. The migration is idempotent.
|
|
217
|
+
|
|
169
218
|
## Contributing
|
|
170
219
|
|
|
171
220
|
Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide.
|
|
@@ -28,9 +28,25 @@ function writeVersion(dir, version, files) {
|
|
|
28
28
|
writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
// src/package-version.ts
|
|
32
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
33
|
+
import { fileURLToPath } from "url";
|
|
34
|
+
import { dirname, join as join2 } from "path";
|
|
35
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
36
|
+
function getPackageVersion() {
|
|
37
|
+
const pkgPath = join2(__dirname, "..", "package.json");
|
|
38
|
+
const raw = readFileSync2(pkgPath, "utf-8");
|
|
39
|
+
const pkg = JSON.parse(raw);
|
|
40
|
+
if (typeof pkg.version !== "string" || pkg.version.length === 0) {
|
|
41
|
+
throw new Error(`Joycraft package.json at ${pkgPath} is missing a version field`);
|
|
42
|
+
}
|
|
43
|
+
return pkg.version;
|
|
44
|
+
}
|
|
45
|
+
|
|
31
46
|
export {
|
|
32
47
|
hashContent,
|
|
33
48
|
readVersion,
|
|
34
|
-
writeVersion
|
|
49
|
+
writeVersion,
|
|
50
|
+
getPackageVersion
|
|
35
51
|
};
|
|
36
|
-
//# sourceMappingURL=chunk-
|
|
52
|
+
//# sourceMappingURL=chunk-4ZI7B4IW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/version.ts","../src/package-version.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { createHash } from 'node:crypto';\n\nconst VERSION_FILE = '.joycraft-version';\n\nexport interface VersionInfo {\n version: string;\n files: Record<string, string>;\n}\n\nexport function hashContent(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\nexport function readVersion(dir: string): VersionInfo | null {\n const filePath = join(dir, VERSION_FILE);\n if (!existsSync(filePath)) return null;\n try {\n const raw = readFileSync(filePath, 'utf-8');\n const parsed = JSON.parse(raw);\n if (typeof parsed.version === 'string' && typeof parsed.files === 'object') {\n return parsed as VersionInfo;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport function writeVersion(dir: string, version: string, files: Record<string, string>): void {\n const filePath = join(dir, VERSION_FILE);\n const data: VersionInfo = { version, files };\n writeFileSync(filePath, JSON.stringify(data, null, 2) + '\\n', 'utf-8');\n}\n\n/**\n * Detect the current Joycraft harness level for a project directory.\n * Returns 5 if Level 5 artifacts (autofix workflow + External Validation) are present, 4 otherwise.\n */\nexport function getLevel(dir: string): number {\n const hasAutofix = existsSync(join(dir, '.github', 'workflows', 'autofix.yml'));\n if (!hasAutofix) return 4;\n const claudeMdPath = join(dir, 'CLAUDE.md');\n if (!existsSync(claudeMdPath)) return 4;\n const content = readFileSync(claudeMdPath, 'utf-8');\n return content.includes('## External Validation') ? 5 : 4;\n}\n","import { readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport function getPackageVersion(): string {\n const pkgPath = join(__dirname, '..', 'package.json');\n const raw = readFileSync(pkgPath, 'utf-8');\n const pkg = JSON.parse(raw) as { version?: unknown };\n if (typeof pkg.version !== 'string' || pkg.version.length === 0) {\n throw new Error(`Joycraft package.json at ${pkgPath} is missing a version field`);\n }\n return pkg.version;\n}\n"],"mappings":";;;AAAA,SAAS,cAAc,eAAe,kBAAkB;AACxD,SAAS,YAAY;AACrB,SAAS,kBAAkB;AAE3B,IAAM,eAAe;AAOd,SAAS,YAAY,SAAyB;AACnD,SAAO,WAAW,QAAQ,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AAC1D;AAEO,SAAS,YAAY,KAAiC;AAC3D,QAAM,WAAW,KAAK,KAAK,YAAY;AACvC,MAAI,CAAC,WAAW,QAAQ,EAAG,QAAO;AAClC,MAAI;AACF,UAAM,MAAM,aAAa,UAAU,OAAO;AAC1C,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,QAAI,OAAO,OAAO,YAAY,YAAY,OAAO,OAAO,UAAU,UAAU;AAC1E,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,aAAa,KAAa,SAAiB,OAAqC;AAC9F,QAAM,WAAW,KAAK,KAAK,YAAY;AACvC,QAAM,OAAoB,EAAE,SAAS,MAAM;AAC3C,gBAAc,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI,MAAM,OAAO;AACvE;;;AClCA,SAAS,gBAAAA,qBAAoB;AAC7B,SAAS,qBAAqB;AAC9B,SAAS,SAAS,QAAAC,aAAY;AAE9B,IAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AAEjD,SAAS,oBAA4B;AAC1C,QAAM,UAAUA,MAAK,WAAW,MAAM,cAAc;AACpD,QAAM,MAAMD,cAAa,SAAS,OAAO;AACzC,QAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,MAAI,OAAO,IAAI,YAAY,YAAY,IAAI,QAAQ,WAAW,GAAG;AAC/D,UAAM,IAAI,MAAM,4BAA4B,OAAO,6BAA6B;AAAA,EAClF;AACA,SAAO,IAAI;AACb;","names":["readFileSync","join"]}
|