prizmkit 1.0.115 → 1.0.118

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "frameworkVersion": "1.0.115",
3
- "bundledAt": "2026-03-26T08:40:28.718Z",
4
- "bundledFrom": "0e9b475"
2
+ "frameworkVersion": "1.0.118",
3
+ "bundledAt": "2026-03-26T15:57:17.490Z",
4
+ "bundledFrom": "f6b1f2d"
5
5
  }
@@ -106,3 +106,30 @@ prizm_check_common_dependencies() {
106
106
  log_warn "Continuing anyway (will fail when spawning sessions)..."
107
107
  fi
108
108
  }
109
+
110
+ # Ensure git is installed and the current directory is a git repository.
111
+ # If git is missing, print install instructions and exit.
112
+ # If not inside a git repo, run git init + initial commit automatically.
113
+ prizm_ensure_git_repo() {
114
+ if ! command -v git &>/dev/null; then
115
+ log_error "git is required but not installed."
116
+ log_error "Install git:"
117
+ log_error " macOS: brew install git or xcode-select --install"
118
+ log_error " Ubuntu: sudo apt-get install git"
119
+ log_error " Windows: https://git-scm.com/download/win"
120
+ exit 1
121
+ fi
122
+
123
+ if ! git rev-parse --is-inside-work-tree &>/dev/null 2>&1; then
124
+ log_warn "Current directory is not a git repository."
125
+ log_info "Initializing git repository..."
126
+ git init -b main
127
+ # Create initial commit so branches and diffs work
128
+ git add -A
129
+ git commit --no-verify -m "chore: initial commit (auto-created by dev-pipeline)" || {
130
+ # If nothing to commit (empty project), create an empty initial commit
131
+ git commit --no-verify --allow-empty -m "chore: initial commit (auto-created by dev-pipeline)"
132
+ }
133
+ log_success "Git repository initialized with initial commit."
134
+ fi
135
+ }
@@ -164,6 +164,7 @@ sys.exit(1)
164
164
  # ============================================================
165
165
 
166
166
  PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
167
+ ORIGINAL_BRANCH=$(git -C "$PROJECT_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
167
168
 
168
169
  log_info "Cleaning $BUG_ID artifacts for full restart..."
169
170
  python3 "$SCRIPTS_DIR/update-bug-status.py" \
@@ -329,9 +330,7 @@ log_info "exit_code=$EXIT_CODE"
329
330
 
330
331
  # ── Determine session outcome from observable signals ──────────────
331
332
  PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
332
- DEFAULT_BRANCH=$(git -C "$PROJECT_ROOT" symbolic-ref refs/remotes/origin/HEAD 2>/dev/null \
333
- | sed 's@^refs/remotes/origin/@@') \
334
- || DEFAULT_BRANCH=$(git -C "$PROJECT_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null | grep -E '^(main|master)$' || echo "main")
333
+ DEFAULT_BRANCH="$ORIGINAL_BRANCH"
335
334
 
336
335
  if [[ $EXIT_CODE -eq 124 ]]; then
337
336
  log_warn "Session timed out after ${SESSION_TIMEOUT}s"
@@ -149,6 +149,7 @@ sys.exit(1)
149
149
  # ============================================================
150
150
 
151
151
  PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
152
+ ORIGINAL_BRANCH=$(git -C "$PROJECT_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
152
153
  FEATURE_SLUG=$(FEATURE_ID="$FEATURE_ID" FEATURE_TITLE="$FEATURE_TITLE" python3 -c "
153
154
  import os, re
154
155
  fid = os.environ['FEATURE_ID'].replace('F-', '').replace('f-', '').zfill(3)
@@ -338,9 +339,7 @@ log_info "exit_code=$EXIT_CODE"
338
339
 
339
340
  # ── Determine session outcome from observable signals ──────────────
340
341
  PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
341
- DEFAULT_BRANCH=$(git -C "$PROJECT_ROOT" symbolic-ref refs/remotes/origin/HEAD 2>/dev/null \
342
- | sed 's@^refs/remotes/origin/@@') \
343
- || DEFAULT_BRANCH=$(git -C "$PROJECT_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null | grep -E '^(main|master)$' || echo "main")
342
+ DEFAULT_BRANCH="$ORIGINAL_BRANCH"
344
343
 
345
344
  if [[ $EXIT_CODE -eq 124 ]]; then
346
345
  log_warn "Session timed out after ${SESSION_TIMEOUT}s"
@@ -272,6 +272,7 @@ trap cleanup SIGINT SIGTERM
272
272
 
273
273
  check_dependencies() {
274
274
  prizm_check_common_dependencies "$CLI_CMD"
275
+ prizm_ensure_git_repo
275
276
  }
276
277
 
277
278
  run_log_cleanup() {
@@ -357,6 +357,7 @@ trap cleanup SIGINT SIGTERM
357
357
 
358
358
  check_dependencies() {
359
359
  prizm_check_common_dependencies "$CLI_CMD"
360
+ prizm_ensure_git_repo
360
361
  }
361
362
 
362
363
  run_log_cleanup() {
@@ -91,7 +91,10 @@ If MISSING — build it now:
91
91
  2. Scan `src/` for files related to this feature; read each one
92
92
  3. Write `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md`:
93
93
  - **Section 1 — Feature Brief**: feature description + acceptance criteria (copy from above)
94
- - **Section 2 — Project Structure**: output of relevant `ls src/` calls
94
+ - **Section 2 — Project Structure**: run the following to get a visual directory tree, then paste output:
95
+ ```bash
96
+ find . -maxdepth 2 -type d -not -path '*/node_modules/*' -not -path '*/.git/*' -not -path '*/dist/*' -not -path '*/build/*' -not -path '*/__pycache__/*' -not -path '*/vendor/*' | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
97
+ ```
95
98
  - **Section 3 — Prizm Context**: content of root.prizm and relevant L1/L2 docs
96
99
  - **Section 4 — Existing Source Files**: **full verbatim content** of each related file in fenced code blocks (with `### path/to/file` heading and line count). Include ALL files needed for implementation and review — downstream phases read this section instead of re-reading individual source files
97
100
  - **Section 5 — Existing Tests**: full content of related test files as code block
@@ -102,7 +102,10 @@ If MISSING — build it now:
102
102
  2. Scan `src/` for files related to this feature; read each one
103
103
  3. Write `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md`:
104
104
  - **Section 1 — Feature Brief**: feature description + acceptance criteria (copy from above)
105
- - **Section 2 — Project Structure**: relevant `ls src/` output
105
+ - **Section 2 — Project Structure**: run the following to get a visual directory tree, then paste output:
106
+ ```bash
107
+ find . -maxdepth 2 -type d -not -path '*/node_modules/*' -not -path '*/.git/*' -not -path '*/dist/*' -not -path '*/build/*' -not -path '*/__pycache__/*' -not -path '*/vendor/*' | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
108
+ ```
106
109
  - **Section 3 — Prizm Context**: full content of root.prizm and relevant L1/L2 docs
107
110
  - **Section 4 — File Manifest**: For each file relevant to this feature, list: file path, why it's needed (modify/reference/test), key interface signatures (function names + params + return types). Do NOT include full file content — agents read files on-demand. Format:
108
111
  ### Files to Modify
@@ -180,7 +180,10 @@ If `EXISTING_CODE` is non-empty: your spec/plan/tasks must reflect this existing
180
180
  2. Scan `src/` for files related to this feature; read each one
181
181
  3. Write `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md`:
182
182
  - **Section 1 — Feature Brief**: feature description + acceptance criteria (copy from above)
183
- - **Section 2 — Project Structure**: relevant `ls src/` output
183
+ - **Section 2 — Project Structure**: run the following to get a visual directory tree, then paste output:
184
+ ```bash
185
+ find . -maxdepth 2 -type d -not -path '*/node_modules/*' -not -path '*/.git/*' -not -path '*/dist/*' -not -path '*/build/*' -not -path '*/__pycache__/*' -not -path '*/vendor/*' | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
186
+ ```
184
187
  - **Section 3 — Prizm Context**: full content of root.prizm and relevant L1/L2 docs
185
188
  - **Section 4 — File Manifest**: For each file relevant to this feature, list: file path, why it's needed (modify/reference/test), key interface signatures (function names + params + return types). Do NOT include full file content — agents read files on-demand. Format:
186
189
  ### Files to Modify
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.115",
2
+ "version": "1.0.118",
3
3
  "skills": {
4
4
  "prizm-kit": {
5
5
  "description": "Full-lifecycle dev toolkit. Covers spec-driven development, Prizm context docs, code quality, debugging, deployment, and knowledge management.",
@@ -49,6 +49,10 @@ Before questions, check optional context files (never block if absent):
49
49
  - `.prizm-docs/root.prizm` (architecture/project context)
50
50
  - `.prizmkit/config.json` (existing stack preferences and detected tech stack)
51
51
  - existing `feature-list.json` (required for incremental mode)
52
+ - If `.prizm-docs/root.prizm` is absent and the project has existing source code, scan the directory structure to understand the codebase layout:
53
+ ```bash
54
+ find . -maxdepth 2 -type d -not -path '*/node_modules/*' -not -path '*/.git/*' -not -path '*/dist/*' -not -path '*/build/*' -not -path '*/__pycache__/*' -not -path '*/vendor/*' | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
55
+ ```
52
56
 
53
57
  **Tech stack auto-population from config.json:**
54
58
  - If `.prizmkit/config.json` contains a `tech_stack` object, use it to pre-fill `global_context` fields in the generated `feature-list.json`.
@@ -227,6 +231,7 @@ AI: "Ready to proceed to dev-pipeline."
227
231
  - new items default `status: "pending"`
228
232
  - English feature titles for stable slug generation
229
233
  - `model` field is optional — omitting it means the pipeline uses $MODEL env or CLI default
234
+ - **descriptions must be implementation-ready** — minimum 15 words (error), recommended 30/50/80 words for low/medium/high complexity (warning). See `planning-guide.md` §4 for what to include.
230
235
 
231
236
  ## Next-Step Execution Policy (after planning)
232
237
 
@@ -174,7 +174,55 @@ F-010: Admin Dashboard (deps: F-006, F-007)
174
174
 
175
175
  ---
176
176
 
177
- ## 4. Acceptance Criteria Writing Guide
177
+ ## 4. Feature Description Writing Guide
178
+
179
+ Feature descriptions are the **primary input** for autonomous pipeline sessions. A thin description forces the AI to guess — producing worse code. Invest in rich descriptions upfront.
180
+
181
+ ### Minimum Word Counts
182
+
183
+ | Complexity | Minimum Words | Warning Threshold |
184
+ |------------|---------------|-------------------|
185
+ | low | 15 | 30 |
186
+ | medium | 15 | 50 |
187
+ | high | 15 | 80 |
188
+
189
+ Below 15 words is a validation error. Below the threshold triggers a warning.
190
+
191
+ ### What to Include
192
+
193
+ Every description should cover these aspects (adapt per feature type):
194
+
195
+ 1. **What to build** — concrete deliverables (API endpoints, UI pages/components, CLI commands, data models)
196
+ 2. **Key behaviors** — business rules, validation, state transitions, workflows
197
+ 3. **Integration points** — which existing modules, services, or APIs it connects to
198
+ 4. **Data model** — entities, relationships, key fields, storage approach (when applicable)
199
+ 5. **Error/edge cases** — failure modes, empty states, limits, unauthorized access
200
+
201
+ ### Good vs Bad Examples
202
+
203
+ **Bad** (17 words — too thin):
204
+ ```
205
+ "Build user authentication with login and registration. Support email/password and social login options."
206
+ ```
207
+
208
+ **Good** (78 words — implementation-ready):
209
+ ```
210
+ "Implement user authentication with email/password registration and login. Create a User model with fields: id, email (unique), password_hash, display_name, created_at, last_login. Build POST /api/auth/register (validate email format, enforce 8+ char password, check uniqueness, hash with bcrypt, return JWT), POST /api/auth/login (verify credentials, issue JWT with 7-day expiry), and GET /api/auth/me (return current user from JWT). Add auth middleware that validates JWT on protected routes. Handle errors: duplicate email (409), invalid credentials (401), expired token (401)."
211
+ ```
212
+
213
+ **Bad** (12 words):
214
+ ```
215
+ "Create the main dashboard page showing project overview and recent activity."
216
+ ```
217
+
218
+ **Good** (65 words):
219
+ ```
220
+ "Build a dashboard page at /dashboard as the post-login landing screen. Display: (1) summary cards showing total projects count, active tasks count, and recent activity count; (2) a recent activity feed listing the last 10 actions across all projects with timestamps; (3) a quick-access project list showing the 5 most recently updated projects. Fetch data via GET /api/dashboard/summary. Show loading skeleton on initial load, empty state when user has no projects."
221
+ ```
222
+
223
+ ---
224
+
225
+ ## 5. Acceptance Criteria Writing Guide
178
226
 
179
227
  Acceptance criteria define what "done" means for a feature. They should be specific, testable, and unambiguous.
180
228
 
@@ -215,7 +263,7 @@ Then [expected outcome]
215
263
 
216
264
  ---
217
265
 
218
- ## 5. Complexity Estimation Guide
266
+ ## 6. Complexity Estimation Guide
219
267
 
220
268
  | Complexity | Characteristics | Typical Scope |
221
269
  |------------|----------------|---------------|
@@ -242,7 +290,7 @@ Consider splitting a feature if it exhibits any of the following:
242
290
 
243
291
  ---
244
292
 
245
- ## 6. Dependency Graph Rules
293
+ ## 7. Dependency Graph Rules
246
294
 
247
295
  These rules ensure the feature dependency graph is valid and buildable.
248
296
 
@@ -270,7 +318,7 @@ These rules ensure the feature dependency graph is valid and buildable.
270
318
 
271
319
  ---
272
320
 
273
- ## 7. Session Granularity Decision Rules
321
+ ## 8. Session Granularity Decision Rules
274
322
 
275
323
  Session granularity determines whether a feature is implemented in a single coding session or split across multiple sub-feature sessions.
276
324
 
@@ -229,6 +229,26 @@ def validate_feature_list(data, planning_mode="new"):
229
229
  if not isinstance(val, str) or not val.strip():
230
230
  errors.append("{}: {} must be a non-empty string".format(label, key))
231
231
 
232
+ # -- Description depth check --
233
+ desc = feat.get("description", "")
234
+ if isinstance(desc, str) and desc.strip():
235
+ word_count = len(desc.split())
236
+ complexity = feat.get("estimated_complexity", "medium")
237
+ min_words = {"low": 30, "medium": 50, "high": 80}.get(complexity, 50)
238
+ if word_count < 15:
239
+ errors.append(
240
+ "{}: description too short ({} words, minimum 15). "
241
+ "Include: what to build, key behaviors, integration points, "
242
+ "and data model overview.".format(label, word_count)
243
+ )
244
+ elif word_count < min_words:
245
+ warnings.append(
246
+ "{}: description only {} words (recommend {}+ for {} complexity). "
247
+ "Richer descriptions produce better pipeline results.".format(
248
+ label, word_count, min_words, complexity
249
+ )
250
+ )
251
+
232
252
  # -- Priority --
233
253
  priority = feat.get("priority")
234
254
  if isinstance(priority, int) and priority > 0:
@@ -49,6 +49,17 @@ BROWNFIELD WORKFLOW (existing project):
49
49
  - SUB-MODULES: directories INSIDE a top-level module (e.g. `src/routes/`, `src/models/`)
50
50
  - A sub-module maps to `.prizm-docs/<M>/<S>.prizm`, never to `.prizm-docs/<S>.prizm` — flattening would create ambiguous paths when two modules have identically-named sub-modules
51
51
  - Exclude: `.git/`, `node_modules/`, `vendor/`, `build/`, `dist/`, `__pycache__/`, `target/`, `bin/`, `.claude/`, `.codebuddy/`, `.prizmkit/`, `.prizm-docs/`, `dev-pipeline/`
52
+ - **Scan command** — run this to get a 2-level directory tree (excludes noise directories):
53
+ ```bash
54
+ find . -maxdepth 2 -type d \
55
+ -not -path '*/node_modules/*' -not -path '*/.git/*' \
56
+ -not -path '*/dist/*' -not -path '*/build/*' \
57
+ -not -path '*/__pycache__/*' -not -path '*/vendor/*' \
58
+ -not -path '*/.claude/*' -not -path '*/.codebuddy/*' \
59
+ -not -path '*/.prizmkit/*' -not -path '*/.prizm-docs/*' \
60
+ -not -path '*/dev-pipeline/*' -not -path '*/target/*' \
61
+ | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
62
+ ```
52
63
  3. Identify entry points by language convention
53
64
  4. Catalog dependencies (external packages)
54
65
  5. Count source files per directory
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prizmkit",
3
- "version": "1.0.115",
3
+ "version": "1.0.118",
4
4
  "description": "Create a new PrizmKit-powered project with clean initialization — no framework dev files, just what you need.",
5
5
  "type": "module",
6
6
  "bin": {