@haposoft/cafekit 0.8.10 → 0.8.11

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Claude Code-first spec-driven workflow and runtime bundle for AI coding assistants.
4
4
 
5
- [![Version](https://img.shields.io/badge/version-0.8.10-blue.svg)](https://github.com/haposoft/cafekit)
5
+ [![Version](https://img.shields.io/badge/version-0.8.11-blue.svg)](https://github.com/haposoft/cafekit)
6
6
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7
7
  [![Claude%20Code](https://img.shields.io/badge/Claude%20Code-Primary-orange.svg)](https://claude.ai/code)
8
8
 
@@ -46,6 +46,7 @@ Claude Code install targets:
46
46
 
47
47
  ```text
48
48
  .claude/
49
+ ├── .gitignore
49
50
  ├── skills/
50
51
  ├── agents/
51
52
  ├── hooks/
package/bin/install.js CHANGED
@@ -751,7 +751,8 @@ function copyClaudeRuntimeFiles(platformKey, results, options = {}) {
751
751
 
752
752
  manifest.runtime.files.forEach(relPath => {
753
753
  const srcPath = path.join(srcBase, relPath);
754
- const targetPath = path.join(targetBase, relPath);
754
+ const targetRelPath = relPath === 'gitignore' ? '.gitignore' : relPath;
755
+ const targetPath = path.join(targetBase, targetRelPath);
755
756
 
756
757
  if (!fs.existsSync(srcPath)) {
757
758
  console.log(` ⚠ Runtime file not found: ${relPath}`);
@@ -767,10 +768,10 @@ function copyClaudeRuntimeFiles(platformKey, results, options = {}) {
767
768
  fs.copyFileSync(srcPath, targetPath);
768
769
 
769
770
  if (targetExists) {
770
- console.log(` ↻ Runtime updated: ${relPath}`);
771
+ console.log(` ↻ Runtime updated: ${targetRelPath}`);
771
772
  results.updated++;
772
773
  } else {
773
- console.log(` ✓ Runtime installed: ${relPath}`);
774
+ console.log(` ✓ Runtime installed: ${targetRelPath}`);
774
775
  results.copied++;
775
776
  }
776
777
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haposoft/cafekit",
3
- "version": "0.8.10",
3
+ "version": "0.8.11",
4
4
  "description": "Claude Code-first spec-driven workflow for AI coding assistants. Bundles CafeKit hapo: skills, runtime hooks, agents, and installer scaffolding.",
5
5
  "author": "Haposoft <nghialt@haposoft.com>",
6
6
  "license": "MIT",
@@ -7,10 +7,12 @@
7
7
  skills/.venv/
8
8
  .venv/
9
9
  venv/
10
+ skills/**/node_modules/
10
11
  __pycache__/
11
12
  *.pyc
12
13
 
13
- # System generated or logs
14
+ # System generated state, caches, and logs
15
+ session-state/
14
16
  hooks/.logs/
15
17
  agent-memory/
16
18
  settings.bak.json
@@ -68,6 +68,7 @@
68
68
  },
69
69
  "runtime": {
70
70
  "files": [
71
+ "gitignore",
71
72
  "runtime.json",
72
73
  "status.cjs",
73
74
  "hooks/session.cjs",
@@ -86,23 +86,31 @@ function extractRequirementIds(requirementsText) {
86
86
  }
87
87
 
88
88
  function validateTaskSections(taskPath, content, errors) {
89
- const hasContext =
90
- hasHeading(content, 'Context') ||
91
- hasHeading(content, 'Objective') ||
92
- hasHeading(content, 'Goal');
89
+ const hasContext = hasHeading(content, 'Context');
90
+ const hasConstraints = hasHeading(content, 'Constraints');
93
91
  const hasSteps =
94
92
  hasHeading(content, 'Steps') || hasHeading(content, 'Implementation Steps');
95
93
  const hasRequirements =
96
94
  hasHeading(content, 'Requirements') || /_Requirements:\s*[^_\n]+_/i.test(content);
95
+ const hasRelatedFiles = hasHeading(content, 'Related Files');
96
+ const hasCompletionCriteria = hasHeading(content, 'Completion Criteria');
97
97
  const hasEvidence =
98
98
  hasHeading(content, 'Evidence') ||
99
99
  hasHeading(content, 'Task Test Plan & Verification Evidence') ||
100
100
  hasHeading(content, 'Verification & Evidence');
101
+ const hasRiskAssessment = hasHeading(content, 'Risk Assessment');
101
102
 
102
- if (!hasContext) errors.push(`${taskPath}: missing Context/Objective/Goal`);
103
+ if (!hasContext) errors.push(`${taskPath}: missing Context`);
104
+ if (!hasConstraints) errors.push(`${taskPath}: missing Constraints`);
103
105
  if (!hasSteps) errors.push(`${taskPath}: missing Steps/Implementation Steps`);
104
106
  if (!hasRequirements) errors.push(`${taskPath}: missing Requirements mapping`);
107
+ if (!hasRelatedFiles) errors.push(`${taskPath}: missing Related Files`);
108
+ if (!hasCompletionCriteria) errors.push(`${taskPath}: missing Completion Criteria`);
105
109
  if (!hasEvidence) errors.push(`${taskPath}: missing Evidence or task test plan`);
110
+ if (!hasRiskAssessment) errors.push(`${taskPath}: missing Risk Assessment`);
111
+ if (hasEvidence && !/Runtime reachability verification/i.test(content)) {
112
+ errors.push(`${taskPath}: missing Runtime reachability verification`);
113
+ }
106
114
  }
107
115
 
108
116
  function validateSpec(specDir) {
@@ -187,6 +195,28 @@ function validateSpec(specDir) {
187
195
  errors.push('tasks/: feature work cannot be entirely R0; reserve R0 for shared foundation tasks');
188
196
  }
189
197
 
198
+ const validationRecommended = spec.design_context?.validation_recommended === true;
199
+ if (taskFiles.length >= 5 && !validationRecommended) {
200
+ errors.push('spec.json.design_context.validation_recommended: must be true for specs with 5+ task files');
201
+ }
202
+ if (
203
+ (validationRecommended || taskFiles.length >= 5) &&
204
+ spec.ready_for_implementation === true &&
205
+ spec.validation?.status !== 'completed'
206
+ ) {
207
+ errors.push(
208
+ 'spec.json.ready_for_implementation: cannot be true when validation is recommended but validation.status is not completed',
209
+ );
210
+ }
211
+ if (spec.validation?.status === 'completed') {
212
+ if (!spec.timestamps?.validation_done) {
213
+ errors.push('spec.json.timestamps.validation_done: required when validation.status is completed');
214
+ }
215
+ if (taskFiles.length >= 5 && !spec.timestamps?.review_done) {
216
+ errors.push('spec.json.timestamps.review_done: required for 5+ task specs after validation');
217
+ }
218
+ }
219
+
190
220
  const requirementsPath = path.join(specDir, 'requirements.md');
191
221
  const designPath = path.join(specDir, 'design.md');
192
222
  const researchPath = path.join(specDir, 'research.md');
@@ -322,12 +322,15 @@ Each task file MUST be **self-contained and implementation-ready** — detailed
322
322
 
323
323
  **Structure per task file:**
324
324
  1. **Context** — why this task exists, current state, target outcome, relevant exact files.
325
- 2. **Steps** — concise implementation checklist with business intent and code-level detail.
326
- 3. **Requirements** — list requirement IDs and acceptance criteria covered by this task.
327
- 4. **Related Files** — table with exact paths, action type, and descriptions when paths are known; otherwise run scout first.
328
- 5. **Completion Criteria** — observable, testable criteria.
329
- 6. **Evidence** — automated command(s), artifact/runtime proof, negative-path proof, and runtime reachability proof.
330
- 7. **Risk Assessment** — table with risk, severity, mitigation.
325
+ 2. **Constraints** — MUST / SHOULD / MUST NOT / SCOPE guardrails.
326
+ 3. **Steps** — concise implementation checklist with business intent and code-level detail.
327
+ 4. **Requirements** — list requirement IDs and acceptance criteria covered by this task.
328
+ 5. **Related Files** — table with exact paths, action type, and descriptions when paths are known; otherwise run scout first.
329
+ 6. **Completion Criteria** — observable, testable criteria.
330
+ 7. **Evidence** — automated command(s), artifact/runtime proof, negative-path proof, and runtime reachability proof.
331
+ 8. **Risk Assessment** — table with risk, severity, mitigation.
332
+
333
+ **Template fidelity is mandatory:** preserve the task template headings exactly. Do NOT rename `## Context` to `## Objective`, do NOT replace `## Completion Criteria` with prose, do NOT remove `## Related Files`, `## Constraints`, or `## Risk Assessment`, and do NOT collapse `## Evidence` into generic QA scenarios. Compact wording is fine; missing sections are invalid.
331
334
 
332
335
  **Parallel markers:** Append `(P)` to tasks that can run concurrently (no data dependency, no shared files, no prerequisite approval from another task). Tasks serving DIFFERENT requirements are often parallelizable.
333
336
 
@@ -368,6 +371,7 @@ Load: `references/review.md` + `rules/design-review.md`
368
371
  - FAIL if a task creates runtime-facing artifacts but neither proves reachability from an entrypoint/caller nor names a later integration task responsible for wiring them.
369
372
  - FAIL if a UI/app/runtime spec has multiple user-facing task outputs but no final integration/reachability task or final integration section.
370
373
  - FAIL if accepted validation decisions exist in reports but are not reflected in the implementation-facing sections of affected artifacts (`Context`, `Steps`, `Requirements`, `Completion Criteria`, `Evidence`, canonical contracts, or requirements text).
374
+ - FAIL if any generated task replaces the required task template with a reduced `Objective` / `Steps` / `Evidence` shape. `Context`, `Constraints`, `Related Files`, `Completion Criteria`, `Evidence`, and `Risk Assessment` must all remain present.
371
375
  - FAIL if the spec scope/provider was switched away from Anthropic/Claude but `requirements.md`, `design.md`, or `tasks/*.md` still contain stale provider-specific strings such as `Claude API`, `Haiku`, or `haiku_reachable`. `research.md` is the only allowed place for historical cost comparisons.
372
376
  - FAIL if privacy/delete-data work lacks a single canonical deletion policy. The design MUST explicitly choose either:
373
377
  1. hard-delete with no re-registration lock, or
@@ -439,7 +443,7 @@ Task paths that omit the `task-` prefix or use non-padded sequence numbers (for
439
443
  6. `task_registry` matches the real filesystem and does not omit any task file
440
444
  7. If `design_context.validation_recommended = true`, `validation.status = "completed"` (or another explicit user-accepted risk state that is recorded)
441
445
 
442
- If any approval is `false`, `ready_for_implementation` MUST remain `false`.
446
+ If any approval is `false`, `ready_for_implementation` MUST remain `false`. If the spec has 5+ task files, `ready_for_implementation` MUST remain `false` until `/hapo:specs <feature> --validate` completes Red Team + Validate and writes `validation.status = "completed"`.
443
447
 
444
448
  ## Output Structure
445
449
 
@@ -27,6 +27,7 @@ Required behavior:
27
27
  4. The final report MUST include the validator command and the final PASS/FAIL result.
28
28
  5. If the validator exits non-zero, final verdict is **FAIL / BLOCKED**, `validation.status` MUST NOT become `completed`, `ready_for_implementation` MUST remain `false`, and the output MUST NOT suggest `/hapo:develop`.
29
29
  6. A markdown checklist, manual QA table, or "all required sections present" claim cannot override validator failure.
30
+ 7. For specs with 5+ task files, a pre-review validator PASS only proves artifact shape. It does not mean implementation can start until Red Team + Validate finish, accepted fixes are propagated, and `spec.json.validation.status` is written as `completed`.
30
31
 
31
32
  ## Auto-Decision: When to Red Team vs Validate
32
33
 
@@ -261,6 +262,8 @@ Before declaring validation complete:
261
262
 
262
263
  #### Step 8: Final Status Write-Back
263
264
  - Update `spec.json.updated_at` to the reconciliation time
265
+ - On final PASS, set `spec.json.validation.status = "completed"`, `spec.json.timestamps.validation_done`, and, when Red Team ran, `spec.json.timestamps.review_done`
266
+ - On final PASS, set `spec.json.ready_for_implementation = true` only after the deterministic validator passes on the final physical artifacts
264
267
  - Ensure `red-team-report.md` and `validate-log.md` do not contradict `spec.json`
265
268
  - If reconciliation or deterministic validation fails, keep `validation.status` as `not-run` or `in_progress`, keep `ready_for_implementation = false`, list blockers explicitly, and do not provide an implementation handoff.
266
269