qualia-framework 6.2.9 → 6.3.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.
Files changed (93) hide show
  1. package/AGENTS.md +1 -0
  2. package/CLAUDE.md +1 -0
  3. package/README.md +26 -30
  4. package/agents/builder.md +7 -7
  5. package/agents/planner.md +39 -3
  6. package/agents/research-synthesizer.md +1 -1
  7. package/agents/researcher.md +3 -3
  8. package/agents/roadmapper.md +7 -7
  9. package/agents/verifier.md +18 -6
  10. package/agents/visual-evaluator.md +8 -7
  11. package/bin/cli.js +160 -16
  12. package/bin/command-surface.js +71 -0
  13. package/bin/contract-runner.js +219 -0
  14. package/bin/harness-eval.js +296 -0
  15. package/bin/host-adapters.js +66 -0
  16. package/bin/install.js +116 -172
  17. package/bin/knowledge-flush.js +21 -10
  18. package/bin/knowledge.js +1 -1
  19. package/bin/plan-contract.js +99 -2
  20. package/bin/planning-hygiene.js +262 -0
  21. package/bin/project-snapshot.js +20 -0
  22. package/bin/report-payload.js +18 -0
  23. package/bin/runtime-manifest.js +35 -0
  24. package/bin/state-ledger.js +184 -0
  25. package/bin/state.js +330 -20
  26. package/bin/trust-score.js +268 -0
  27. package/bin/work-packet.js +228 -0
  28. package/docs/erp-contract.md +81 -1
  29. package/docs/onboarding.html +4 -14
  30. package/guide.md +16 -16
  31. package/hooks/fawzi-approval-guard.js +143 -0
  32. package/hooks/pre-deploy-gate.js +74 -1
  33. package/hooks/session-start.js +29 -1
  34. package/package.json +1 -1
  35. package/qualia-design/design-rubric.md +17 -5
  36. package/qualia-design/frontend.md +6 -2
  37. package/qualia-design/graphics.md +47 -0
  38. package/rules/codex-goal.md +1 -1
  39. package/rules/command-output.md +35 -0
  40. package/rules/one-opinion.md +2 -2
  41. package/rules/speed.md +0 -1
  42. package/skills/qualia/SKILL.md +12 -12
  43. package/skills/qualia-build/SKILL.md +20 -14
  44. package/skills/qualia-discuss/SKILL.md +10 -10
  45. package/skills/qualia-doctor/SKILL.md +140 -0
  46. package/skills/qualia-feature/SKILL.md +24 -22
  47. package/skills/qualia-fix/SKILL.md +216 -0
  48. package/skills/qualia-handoff/SKILL.md +9 -9
  49. package/skills/qualia-learn/SKILL.md +11 -11
  50. package/skills/qualia-map/SKILL.md +2 -2
  51. package/skills/qualia-milestone/SKILL.md +15 -15
  52. package/skills/qualia-new/REFERENCE.md +9 -9
  53. package/skills/qualia-new/SKILL.md +14 -14
  54. package/skills/qualia-optimize/REFERENCE.md +1 -1
  55. package/skills/qualia-optimize/SKILL.md +23 -16
  56. package/skills/qualia-plan/SKILL.md +23 -13
  57. package/skills/qualia-polish/REFERENCE.md +15 -15
  58. package/skills/qualia-polish/SKILL.md +81 -21
  59. package/skills/qualia-polish/scripts/loop.mjs +3 -3
  60. package/skills/qualia-polish/scripts/score.mjs +9 -3
  61. package/skills/{qualia-vibe/scripts/extract.mjs → qualia-polish/scripts/vibe-extract.mjs} +5 -5
  62. package/skills/{qualia-vibe/scripts/tokens.mjs → qualia-polish/scripts/vibe-tokens.mjs} +6 -6
  63. package/skills/qualia-postmortem/SKILL.md +9 -9
  64. package/skills/qualia-report/SKILL.md +23 -23
  65. package/skills/qualia-research/SKILL.md +5 -5
  66. package/skills/qualia-review/SKILL.md +28 -12
  67. package/skills/qualia-road/SKILL.md +30 -22
  68. package/skills/qualia-ship/SKILL.md +31 -24
  69. package/skills/qualia-test/SKILL.md +5 -5
  70. package/skills/qualia-verify/SKILL.md +45 -23
  71. package/skills/zoho-workflow/SKILL.md +1 -1
  72. package/templates/help.html +11 -20
  73. package/tests/bin.test.sh +178 -76
  74. package/tests/hooks.test.sh +81 -1
  75. package/tests/install-smoke.test.sh +35 -5
  76. package/tests/lib.test.sh +432 -0
  77. package/tests/published-install-smoke.test.sh +4 -3
  78. package/tests/refs.test.sh +9 -4
  79. package/tests/runner.js +32 -28
  80. package/tests/skills.test.sh +4 -4
  81. package/tests/state.test.sh +133 -3
  82. package/skills/qualia-debug/SKILL.md +0 -185
  83. package/skills/qualia-flush/SKILL.md +0 -198
  84. package/skills/qualia-help/SKILL.md +0 -74
  85. package/skills/qualia-hook-gen/SKILL.md +0 -206
  86. package/skills/qualia-idk/SKILL.md +0 -166
  87. package/skills/qualia-issues/SKILL.md +0 -151
  88. package/skills/qualia-pause/SKILL.md +0 -68
  89. package/skills/qualia-resume/SKILL.md +0 -52
  90. package/skills/qualia-skill-new/SKILL.md +0 -173
  91. package/skills/qualia-triage/SKILL.md +0 -152
  92. package/skills/qualia-vibe/SKILL.md +0 -226
  93. package/skills/qualia-zoom/SKILL.md +0 -51
package/tests/bin.test.sh CHANGED
@@ -137,7 +137,7 @@ TMP=$(mktmp)
137
137
  mkdir -p "$TMP/.claude"
138
138
  cat > "$TMP/.claude/.qualia-config.json" <<'EOF'
139
139
  {
140
- "code": "QS-FAWZI-01",
140
+ "code": "QS-FAWZI-11",
141
141
  "installed_by": "Fawzi Goussous",
142
142
  "role": "OWNER",
143
143
  "version": "2.8.1",
@@ -421,7 +421,7 @@ TMP=$(mktmp)
421
421
  mkdir -p "$TMP/.claude"
422
422
  cat > "$TMP/.claude/.qualia-config.json" <<'EOF'
423
423
  {
424
- "code": "QS-FAWZI-01",
424
+ "code": "QS-FAWZI-11",
425
425
  "installed_by": "Fawzi Goussous",
426
426
  "role": "OWNER",
427
427
  "version": "2.8.1",
@@ -446,23 +446,32 @@ echo "install.js:"
446
446
 
447
447
  # 28. Happy path: valid code installs everything
448
448
  TMP=$(mktmp)
449
- echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out.log" 2>&1
449
+ echo "QS-FAWZI-11" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out.log" 2>&1
450
450
  EXIT=$?
451
451
  if [ "$EXIT" -eq 0 ] \
452
452
  && [ -f "$TMP/.claude/skills/qualia/SKILL.md" ] \
453
453
  && [ -f "$TMP/.claude/hooks/session-start.js" ] \
454
454
  && [ -f "$TMP/.claude/bin/state.js" ] \
455
+ && [ -f "$TMP/.claude/bin/runtime-manifest.js" ] \
456
+ && [ -f "$TMP/.claude/bin/command-surface.js" ] \
457
+ && [ -f "$TMP/.claude/bin/host-adapters.js" ] \
455
458
  && [ -f "$TMP/.claude/bin/qualia-ui.js" ] \
456
459
  && [ -f "$TMP/.claude/bin/statusline.js" ] \
460
+ && [ -f "$TMP/.claude/bin/state-ledger.js" ] \
461
+ && [ -f "$TMP/.claude/bin/contract-runner.js" ] \
462
+ && [ -f "$TMP/.claude/bin/harness-eval.js" ] \
463
+ && [ -f "$TMP/.claude/bin/trust-score.js" ] \
464
+ && [ -f "$TMP/.claude/bin/work-packet.js" ] \
457
465
  && [ -f "$TMP/.claude/bin/project-snapshot.js" ] \
466
+ && [ -f "$TMP/.claude/bin/planning-hygiene.js" ] \
458
467
  && [ -f "$TMP/.claude/.qualia-config.json" ]; then
459
- pass "QS-FAWZI-01 → installs skills, hooks, bin/, config"
468
+ pass "QS-FAWZI-11 → installs skills, hooks, bin/, config"
460
469
  else
461
- fail_case "QS-FAWZI-01 happy path" "exit=$EXIT"
470
+ fail_case "QS-FAWZI-11 happy path" "exit=$EXIT"
462
471
  fi
463
472
 
464
473
  # 29. Config JSON has correct fields after happy path
465
- if grep -q '"code": "QS-FAWZI-01"' "$TMP/.claude/.qualia-config.json" \
474
+ if grep -q '"code": "QS-FAWZI-11"' "$TMP/.claude/.qualia-config.json" \
466
475
  && grep -q '"installed_by": "Fawzi Goussous"' "$TMP/.claude/.qualia-config.json" \
467
476
  && grep -q '"role": "OWNER"' "$TMP/.claude/.qualia-config.json"; then
468
477
  pass "config JSON has code, installed_by, role=OWNER"
@@ -478,13 +487,13 @@ else
478
487
  fail_case "CLAUDE.md role substitution"
479
488
  fi
480
489
 
481
- # 31. All 11 hooks installed (block-env-edit removed in v3.2.0;
490
+ # 31. All 12 hooks installed (block-env-edit removed in v3.2.0;
482
491
  # git-guardrails + stop-session-log added in v4.2.0;
483
492
  # vercel-account-guard + env-empty-guard + supabase-destructive-guard added in v5.0.0;
484
- # pre-compact removed in v6.2.0)
493
+ # pre-compact removed in v6.2.0; fawzi-approval-guard added in v6.2.11)
485
494
  HOOK_COUNT=$(ls "$TMP/.claude/hooks/"*.js 2>/dev/null | wc -l)
486
- if [ "$HOOK_COUNT" -eq 11 ]; then
487
- pass "11 hooks installed in hooks/"
495
+ if [ "$HOOK_COUNT" -eq 12 ]; then
496
+ pass "12 hooks installed in hooks/"
488
497
  else
489
498
  fail_case "hook count" "got $HOOK_COUNT"
490
499
  fi
@@ -500,7 +509,7 @@ else
500
509
  fail_case "settings.json contents"
501
510
  fi
502
511
 
503
- # 33. settings.json contains all 11 hooks wired correctly
512
+ # 33. settings.json contains all 12 hooks wired correctly
504
513
  # pre-compact.js was removed in v6.2.0 — verify it's NOT in settings.json.
505
514
  if grep -q 'branch-guard.js' "$TMP/.claude/settings.json" \
506
515
  && grep -q 'migration-guard.js' "$TMP/.claude/settings.json" \
@@ -511,33 +520,34 @@ if grep -q 'branch-guard.js' "$TMP/.claude/settings.json" \
511
520
  && grep -q 'git-guardrails.js' "$TMP/.claude/settings.json" \
512
521
  && grep -q 'stop-session-log.js' "$TMP/.claude/settings.json" \
513
522
  && grep -q 'vercel-account-guard.js' "$TMP/.claude/settings.json" \
523
+ && grep -q 'fawzi-approval-guard.js' "$TMP/.claude/settings.json" \
514
524
  && grep -q 'env-empty-guard.js' "$TMP/.claude/settings.json" \
515
525
  && grep -q 'supabase-destructive-guard.js' "$TMP/.claude/settings.json" \
516
526
  && ! grep -q 'pre-compact.js' "$TMP/.claude/settings.json"; then
517
- pass "settings.json has all 11 hooks wired (no pre-compact)"
527
+ pass "settings.json has all 12 hooks wired (no pre-compact)"
518
528
  else
519
529
  fail_case "settings.json hooks misconfigured (check for stale pre-compact entry)"
520
530
  fi
521
531
 
522
532
  # 34. Lowercase code works (resolveTeamCode normalizes)
523
533
  TMP=$(mktmp)
524
- echo "qs-fawzi-01" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out.log" 2>&1
534
+ echo "qs-fawzi-11" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out.log" 2>&1
525
535
  EXIT=$?
526
536
  if [ "$EXIT" -eq 0 ] \
527
537
  && [ -f "$TMP/.claude/.qualia-config.json" ] \
528
- && grep -q '"code": "QS-FAWZI-01"' "$TMP/.claude/.qualia-config.json"; then
529
- pass "lowercase 'qs-fawzi-01' → canonical 'QS-FAWZI-01'"
538
+ && grep -q '"code": "QS-FAWZI-11"' "$TMP/.claude/.qualia-config.json"; then
539
+ pass "lowercase 'qs-fawzi-11' → canonical 'QS-FAWZI-11'"
530
540
  else
531
541
  fail_case "lowercase normalization" "exit=$EXIT"
532
542
  fi
533
543
 
534
- # 34. O/0 typo tolerance — letter O in suffix normalized to digit 0
544
+ # 34b. O/0 typo tolerance — letter O in suffix normalized to digit 0
535
545
  TMP=$(mktmp)
536
- echo "QS-FAWZI-O1" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out.log" 2>&1
546
+ echo "QS-HASAN-O2" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out.log" 2>&1
537
547
  EXIT=$?
538
548
  if [ "$EXIT" -eq 0 ] \
539
549
  && [ -f "$TMP/.claude/.qualia-config.json" ] \
540
- && grep -q '"code": "QS-FAWZI-01"' "$TMP/.claude/.qualia-config.json"; then
550
+ && grep -q '"code": "QS-HASAN-02"' "$TMP/.claude/.qualia-config.json"; then
541
551
  pass "letter 'O' in suffix → normalized to digit '0'"
542
552
  else
543
553
  fail_case "O/0 fuzzy match" "exit=$EXIT"
@@ -592,10 +602,10 @@ fi
592
602
 
593
603
  # 39. Code with surrounding whitespace is accepted
594
604
  TMP=$(mktmp)
595
- printf ' QS-FAWZI-01 \n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out.log" 2>&1
605
+ printf ' QS-FAWZI-11 \n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out.log" 2>&1
596
606
  EXIT=$?
597
607
  if [ "$EXIT" -eq 0 ] \
598
- && grep -q '"code": "QS-FAWZI-01"' "$TMP/.claude/.qualia-config.json"; then
608
+ && grep -q '"code": "QS-FAWZI-11"' "$TMP/.claude/.qualia-config.json"; then
599
609
  pass "whitespace-padded code → accepted and trimmed"
600
610
  else
601
611
  fail_case "whitespace trim" "exit=$EXIT"
@@ -612,7 +622,7 @@ cat > "$TMP/.claude/settings.json" <<'EOF'
612
622
  }
613
623
  }
614
624
  EOF
615
- echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out.log" 2>&1
625
+ echo "QS-FAWZI-11" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out.log" 2>&1
616
626
  EXIT=$?
617
627
  MERGED=$($NODE -e 'const s=JSON.parse(require("fs").readFileSync(process.argv[1],"utf8"));console.log([s.customKey,s.env&&s.env.MY_CUSTOM_VAR,s.env&&s.env.CLAUDE_CODE_NO_FLICKER,!!s.hooks,!!s.statusLine].join("|"))' "$TMP/.claude/settings.json" 2>/dev/null)
618
628
  if [ "$EXIT" -eq 0 ] \
@@ -624,7 +634,7 @@ fi
624
634
 
625
635
  # 41. Knowledge files created on first install
626
636
  TMP=$(mktmp)
627
- echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out.log" 2>&1
637
+ echo "QS-FAWZI-11" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out.log" 2>&1
628
638
  EXIT=$?
629
639
  if [ "$EXIT" -eq 0 ] \
630
640
  && [ -f "$TMP/.claude/knowledge/learned-patterns.md" ] \
@@ -637,7 +647,7 @@ fi
637
647
 
638
648
  # 42. Idempotent re-install preserves user edits to knowledge files
639
649
  printf '\n## CUSTOM LEARNING — DO NOT OVERWRITE\n' >> "$TMP/.claude/knowledge/learned-patterns.md"
640
- echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out2.log" 2>&1
650
+ echo "QS-FAWZI-11" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out2.log" 2>&1
641
651
  EXIT=$?
642
652
  if [ "$EXIT" -eq 0 ] \
643
653
  && grep -q "CUSTOM LEARNING" "$TMP/.claude/knowledge/learned-patterns.md"; then
@@ -652,7 +662,7 @@ if [ ! -f "$TMP/.claude/.erp-api-key" ] && [ "$CONFIG_ENABLED" = "disabled" ]; t
652
662
  echo " ✓ ERP disabled when no API key is provided"
653
663
  PASS=$((PASS + 1))
654
664
  echo "custom-erp-key" > "$TMP/.claude/.erp-api-key"
655
- echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out3.log" 2>&1
665
+ echo "QS-FAWZI-11" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out3.log" 2>&1
656
666
  if grep -q "custom-erp-key" "$TMP/.claude/.erp-api-key"; then
657
667
  pass ".erp-api-key preserved on re-install"
658
668
  else
@@ -664,7 +674,7 @@ fi
664
674
 
665
675
  # 44. Templates copied to qualia-templates/
666
676
  TMP=$(mktmp)
667
- echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out.log" 2>&1
677
+ echo "QS-FAWZI-11" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/out.log" 2>&1
668
678
  EXIT=$?
669
679
  TMPL_COUNT=$(ls "$TMP/.claude/qualia-templates/" 2>/dev/null | wc -l)
670
680
  if [ "$EXIT" -eq 0 ] && [ "$TMPL_COUNT" -gt 0 ]; then
@@ -689,6 +699,20 @@ else
689
699
  fail_case "rules copied" "count=$RULE_COUNT"
690
700
  fi
691
701
 
702
+ # 46b. Command output transparency rule installs
703
+ if [ -f "$TMP/.claude/rules/command-output.md" ] && grep -q "alwaysApply: true" "$TMP/.claude/rules/command-output.md"; then
704
+ pass "command-output rule installs"
705
+ else
706
+ fail_case "command-output rule missing or not always-on after install"
707
+ fi
708
+
709
+ # 46c. Complex graphics design substrate installs
710
+ if [ -f "$TMP/.claude/qualia-design/graphics.md" ]; then
711
+ pass "graphics design substrate installs"
712
+ else
713
+ fail_case "graphics.md missing after install"
714
+ fi
715
+
692
716
  # 47. Config version matches package.json version
693
717
  if grep -q "\"version\": \"$PKG_VERSION\"" "$TMP/.claude/.qualia-config.json"; then
694
718
  pass "config version matches package.json ($PKG_VERSION)"
@@ -699,13 +723,14 @@ fi
699
723
  echo ""
700
724
  echo "--- v4.2.0 phase 3 (flush + forks + model matrix) ---"
701
725
 
702
- # 61. qualia-flush skill installs
726
+ # 61. qualia-flush is retired from the default slash-command surface
703
727
  TMP=$(mktmp)
704
- echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" >/dev/null 2>&1
705
- if [ -f "$TMP/.claude/skills/qualia-flush/SKILL.md" ]; then
706
- pass "qualia-flush skill installs"
728
+ echo "QS-FAWZI-11" | HOME="$TMP" $NODE "$INSTALL_JS" >/dev/null 2>&1
729
+ if [ ! -f "$TMP/.claude/skills/qualia-flush/SKILL.md" ] \
730
+ && [ -f "$TMP/.claude/bin/knowledge-flush.js" ]; then
731
+ pass "qualia-flush retired; knowledge-flush.js remains installed"
707
732
  else
708
- fail_case "qualia-flush skill missing after install"
733
+ fail_case "qualia-flush retirement/install state"
709
734
  fi
710
735
 
711
736
  # 62. CLAUDE_AGENT_FORK_ENABLED=1 in settings.json
@@ -946,7 +971,7 @@ fi
946
971
 
947
972
  # 70. qualia-postmortem skill installs
948
973
  TMP=$(mktmp)
949
- echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" >/dev/null 2>&1
974
+ echo "QS-FAWZI-11" | HOME="$TMP" $NODE "$INSTALL_JS" >/dev/null 2>&1
950
975
  if [ -f "$TMP/.claude/skills/qualia-postmortem/SKILL.md" ]; then
951
976
  pass "qualia-postmortem skill installs"
952
977
  else
@@ -1023,7 +1048,7 @@ echo "--- v5.0.0 (alignment substrate + new skills) ---"
1023
1048
 
1024
1049
  # 79. CONTEXT.md template installs to qualia-templates/
1025
1050
  TMP=$(mktmp)
1026
- echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" >/dev/null 2>&1
1051
+ echo "QS-FAWZI-11" | HOME="$TMP" $NODE "$INSTALL_JS" >/dev/null 2>&1
1027
1052
  if [ -f "$TMP/.claude/qualia-templates/CONTEXT.md" ]; then
1028
1053
  pass "CONTEXT.md template installs to qualia-templates/"
1029
1054
  else
@@ -1037,12 +1062,17 @@ else
1037
1062
  fail_case "decisions/ADR-template.md missing"
1038
1063
  fi
1039
1064
 
1040
- # 81-84. The 4 new v5 skills install with their SKILL.md
1041
- for SKILL in qualia-zoom qualia-road qualia-issues qualia-triage; do
1042
- if [ -f "$TMP/.claude/skills/$SKILL/SKILL.md" ]; then
1043
- pass "$SKILL skill installs"
1065
+ # 81-84. v6.3 keeps road active and retires queue/zoom helper commands
1066
+ if [ -f "$TMP/.claude/skills/qualia-road/SKILL.md" ]; then
1067
+ pass "qualia-road skill installs"
1068
+ else
1069
+ fail_case "qualia-road skill missing after install"
1070
+ fi
1071
+ for SKILL in qualia-zoom qualia-issues qualia-triage; do
1072
+ if [ ! -f "$TMP/.claude/skills/$SKILL/SKILL.md" ]; then
1073
+ pass "$SKILL retired from default install"
1044
1074
  else
1045
- fail_case "$SKILL skill missing after install"
1075
+ fail_case "$SKILL should be retired from default install"
1046
1076
  fi
1047
1077
  done
1048
1078
 
@@ -1089,12 +1119,11 @@ else
1089
1119
  fail_case "builder.md missing Trust boundary block"
1090
1120
  fi
1091
1121
 
1092
- # 91. qualia-issues uses --body-file (not vulnerable heredoc) for gh issue create
1093
- if grep -q -- "--body-file" "$TMP/.claude/skills/qualia-issues/SKILL.md" \
1094
- && ! grep -q "gh issue create.*--body \"\$(cat <<" "$TMP/.claude/skills/qualia-issues/SKILL.md"; then
1095
- pass "qualia-issues uses --body-file (no heredoc shell injection)"
1122
+ # 91. qualia-issues source is removed from the shipped command surface
1123
+ if [ ! -d "$FRAMEWORK_DIR/skills/qualia-issues" ]; then
1124
+ pass "qualia-issues source removed from shipped command surface"
1096
1125
  else
1097
- fail_case "qualia-issues still uses heredoc for gh issue body"
1126
+ fail_case "qualia-issues source directory should not be shipped"
1098
1127
  fi
1099
1128
 
1100
1129
  # 92-94. v5.0 insights-driven hooks parse as valid Node and install
@@ -1154,7 +1183,7 @@ echo "--- v5.0.0 (visual-polish loop addendum) ---"
1154
1183
 
1155
1184
  # 99. qualia-polish SKILL.md installs (v5.8: polish-loop consolidated into --loop flag)
1156
1185
  TMP=$(mktmp)
1157
- echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" >/dev/null 2>&1
1186
+ echo "QS-FAWZI-11" | HOME="$TMP" $NODE "$INSTALL_JS" >/dev/null 2>&1
1158
1187
  if [ -f "$TMP/.claude/skills/qualia-polish/SKILL.md" ]; then
1159
1188
  pass "qualia-polish SKILL.md installs"
1160
1189
  else
@@ -1204,16 +1233,16 @@ else
1204
1233
  fi
1205
1234
 
1206
1235
  # 105. score.mjs computes pass correctly (all dims >= 3)
1207
- SCORE_OUT=$(echo '{"typography":3,"color":3,"spatial":3,"layout":3,"shadow":3,"motion":3,"microcopy":3,"container":3}' | $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/score.mjs" 2>&1)
1236
+ SCORE_OUT=$(echo '{"typography":3,"color":3,"spatial":3,"layout":3,"shadow":3,"motion":3,"microcopy":3,"container":3,"graphics":3}' | $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/score.mjs" 2>&1)
1208
1237
  EXIT=$?
1209
- if [ "$EXIT" -eq 0 ] && echo "$SCORE_OUT" | grep -q '"pass": true'; then
1238
+ if [ "$EXIT" -eq 0 ] && echo "$SCORE_OUT" | grep -q '"pass": true' && echo "$SCORE_OUT" | grep -q '"max": 45'; then
1210
1239
  pass "score.mjs pass on all-3 scores"
1211
1240
  else
1212
1241
  fail_case "score.mjs pass computation" "exit=$EXIT"
1213
1242
  fi
1214
1243
 
1215
1244
  # 106. score.mjs computes fail correctly (one dim < 3)
1216
- SCORE_OUT=$(echo '{"typography":2,"color":3,"spatial":3,"layout":3,"shadow":3,"motion":3,"microcopy":3,"container":3}' | $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/score.mjs" 2>&1)
1245
+ SCORE_OUT=$(echo '{"typography":2,"color":3,"spatial":3,"layout":3,"shadow":3,"motion":3,"microcopy":3,"container":3,"graphics":3}' | $NODE "$FRAMEWORK_DIR/skills/qualia-polish/scripts/score.mjs" 2>&1)
1217
1246
  EXIT=$?
1218
1247
  if [ "$EXIT" -eq 1 ] && echo "$SCORE_OUT" | grep -q '"pass": false'; then
1219
1248
  pass "score.mjs fail on dim < 3"
@@ -1305,7 +1334,7 @@ for ITER in 1 2 3; do
1305
1334
  "iteration": $ITER,
1306
1335
  "tokens_used": 100,
1307
1336
  "viewport_results": [],
1308
- "aggregate_scores": {"typography":1,"color":3,"spatial":3,"layout":3,"shadow":3,"motion":3,"microcopy":3,"container":3},
1337
+ "aggregate_scores": {"typography":1,"color":3,"spatial":3,"layout":3,"shadow":3,"motion":3,"microcopy":3,"container":3,"graphics":3},
1309
1338
  "top_issues": [{"dim":"typography","severity":"critical","description":"banned font Inter visible","likely_file":"src/styles.css","fix":"replace"}],
1310
1339
  "pass": false
1311
1340
  }
@@ -1333,7 +1362,7 @@ echo "--- v5.1.0 (multi-target install: Claude / Codex / Both) ---"
1333
1362
 
1334
1363
  # 118. Target=1 (Claude only) installs to ~/.claude/, not ~/.codex/
1335
1364
  TMP=$(mktmp)
1336
- printf 'QS-FAWZI-01\n1\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1365
+ printf 'QS-FAWZI-11\n1\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1337
1366
  EXIT=$?
1338
1367
  if [ "$EXIT" -eq 0 ] \
1339
1368
  && [ -f "$TMP/.claude/.qualia-config.json" ] \
@@ -1345,21 +1374,33 @@ fi
1345
1374
 
1346
1375
  # 119. Target=2 (Codex only) writes native Codex runtime files, skips ~/.claude/
1347
1376
  TMP=$(mktmp)
1348
- printf 'QS-FAWZI-01\n2\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1377
+ printf 'QS-FAWZI-11\n2\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1349
1378
  EXIT=$?
1350
1379
  if [ "$EXIT" -eq 0 ] \
1351
1380
  && [ -f "$TMP/.codex/AGENTS.md" ] \
1352
1381
  && [ -f "$TMP/.codex/.qualia-config.json" ] \
1353
1382
  && [ -f "$TMP/.codex/config.toml" ] \
1354
1383
  && [ -f "$TMP/.codex/hooks.json" ] \
1384
+ && [ -f "$TMP/.codex/bin/runtime-manifest.js" ] \
1385
+ && [ -f "$TMP/.codex/bin/command-surface.js" ] \
1386
+ && [ -f "$TMP/.codex/bin/host-adapters.js" ] \
1355
1387
  && [ -f "$TMP/.codex/bin/statusline.js" ] \
1388
+ && [ -f "$TMP/.codex/bin/state-ledger.js" ] \
1389
+ && [ -f "$TMP/.codex/bin/contract-runner.js" ] \
1390
+ && [ -f "$TMP/.codex/bin/harness-eval.js" ] \
1391
+ && [ -f "$TMP/.codex/bin/trust-score.js" ] \
1392
+ && [ -f "$TMP/.codex/bin/work-packet.js" ] \
1356
1393
  && [ -f "$TMP/.codex/bin/project-snapshot.js" ] \
1394
+ && [ -f "$TMP/.codex/bin/planning-hygiene.js" ] \
1357
1395
  && [ -f "$TMP/.codex/agents/planner.toml" ] \
1358
1396
  && [ -f "$TMP/.codex/skills/qualia-new/SKILL.md" ] \
1359
1397
  && [ -f "$TMP/.codex/qualia-references/questioning.md" ] \
1360
1398
  && [ ! -d "$TMP/.claude" ] \
1361
1399
  && grep -q "Role: OWNER" "$TMP/.codex/AGENTS.md" \
1362
1400
  && ! grep -q "{{ROLE}}" "$TMP/.codex/AGENTS.md" \
1401
+ && grep -q "status_line" "$TMP/.codex/config.toml" \
1402
+ && grep -q "model-with-reasoning" "$TMP/.codex/config.toml" \
1403
+ && grep -q "task-progress" "$TMP/.codex/config.toml" \
1363
1404
  && grep -q "pre-deploy-gate.js" "$TMP/.codex/hooks.json" \
1364
1405
  && grep -q "developer_instructions" "$TMP/.codex/agents/planner.toml" \
1365
1406
  && ! grep -R "\.claude/bin" "$TMP/.codex/skills" >/dev/null 2>&1; then
@@ -1371,6 +1412,7 @@ fi
1371
1412
  EXIT=0; HOME="$TMP" $NODE "$CLI_JS" doctor > "$TMP/doctor.log" 2>&1 || EXIT=$?
1372
1413
  if [ "$EXIT" -eq 0 ] \
1373
1414
  && grep -q "Codex hooks.json PreToolUse" "$TMP/doctor.log" \
1415
+ && grep -q "Codex config.toml TUI status_line" "$TMP/doctor.log" \
1374
1416
  && grep -q "All checks passed" "$TMP/doctor.log"; then
1375
1417
  pass "doctor passes for Codex-only install"
1376
1418
  else
@@ -1388,7 +1430,7 @@ fi
1388
1430
 
1389
1431
  # 120. Target=3 (Both) populates both directories with the right artifacts
1390
1432
  TMP=$(mktmp)
1391
- printf 'QS-FAWZI-01\n3\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1433
+ printf 'QS-FAWZI-11\n3\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1392
1434
  EXIT=$?
1393
1435
  if [ "$EXIT" -eq 0 ] \
1394
1436
  && [ -f "$TMP/.claude/.qualia-config.json" ] \
@@ -1407,7 +1449,7 @@ fi
1407
1449
  # 121. Backward compat: legacy single-line piped install (no target line)
1408
1450
  # defaults to Claude only. Same exact invocation as pre-v5.1.
1409
1451
  TMP=$(mktmp)
1410
- echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1452
+ echo "QS-FAWZI-11" | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1411
1453
  EXIT=$?
1412
1454
  if [ "$EXIT" -eq 0 ] \
1413
1455
  && [ -f "$TMP/.claude/.qualia-config.json" ] \
@@ -1422,7 +1464,7 @@ fi
1422
1464
  TMP=$(mktmp)
1423
1465
  mkdir -p "$TMP/.codex"
1424
1466
  echo "OLD USER CONTENT" > "$TMP/.codex/AGENTS.md"
1425
- printf 'QS-FAWZI-01\n2\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1467
+ printf 'QS-FAWZI-11\n2\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1426
1468
  EXIT=$?
1427
1469
  BAK_COUNT=$(ls "$TMP/.codex/"AGENTS.md.bak.* 2>/dev/null | wc -l)
1428
1470
  if [ "$EXIT" -eq 0 ] \
@@ -1437,9 +1479,9 @@ fi
1437
1479
  # 123. Codex install with same content does NOT create a redundant .bak
1438
1480
  # (the v5.0 CLAUDE.md backup discipline only backs up if content differs).
1439
1481
  TMP=$(mktmp)
1440
- printf 'QS-FAWZI-01\n2\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1482
+ printf 'QS-FAWZI-11\n2\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1441
1483
  # Re-run with same input — content should be identical, no new backup.
1442
- printf 'QS-FAWZI-01\n2\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log2.txt" 2>&1
1484
+ printf 'QS-FAWZI-11\n2\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log2.txt" 2>&1
1443
1485
  BAK_COUNT=$(ls "$TMP/.codex/"AGENTS.md.bak.* 2>/dev/null | wc -l)
1444
1486
  if [ "$BAK_COUNT" -eq 0 ]; then
1445
1487
  pass "Codex re-install with identical content → no redundant .bak"
@@ -1464,7 +1506,7 @@ cat > "$TMP/.codex/hooks.json" <<'JSON'
1464
1506
  }
1465
1507
  }
1466
1508
  JSON
1467
- printf 'QS-FAWZI-01\n2\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1509
+ printf 'QS-FAWZI-11\n2\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1468
1510
  if grep -q "custom-session-hook.js" "$TMP/.codex/hooks.json" \
1469
1511
  && grep -q "session-start.js" "$TMP/.codex/hooks.json"; then
1470
1512
  pass "Codex hooks.json merge preserves non-Qualia hooks"
@@ -1490,7 +1532,7 @@ cat > "$TMP/.codex/hooks.json" <<'JSON'
1490
1532
  }
1491
1533
  }
1492
1534
  JSON
1493
- printf 'QS-FAWZI-01\n2\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1535
+ printf 'QS-FAWZI-11\n2\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1494
1536
  EXIT=0; HOME="$TMP" $NODE "$CLI_JS" uninstall --yes > "$TMP/uninstall.log" 2>&1 || EXIT=$?
1495
1537
  if [ "$EXIT" -eq 0 ] \
1496
1538
  && [ -f "$TMP/.codex/AGENTS.md" ] \
@@ -1510,7 +1552,7 @@ fi
1510
1552
 
1511
1553
  # 123d. Team management writes to Codex-only installs without creating ~/.claude.
1512
1554
  TMP=$(mktmp)
1513
- printf 'QS-FAWZI-01\n2\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1555
+ printf 'QS-FAWZI-11\n2\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1514
1556
  EXIT=0; HOME="$TMP" $NODE "$CLI_JS" team add --code QS-TEST-99 --name "Test User" > "$TMP/team.log" 2>&1 || EXIT=$?
1515
1557
  if [ "$EXIT" -eq 0 ] \
1516
1558
  && [ -f "$TMP/.codex/.qualia-team.json" ] \
@@ -1525,7 +1567,7 @@ fi
1525
1567
  # sequences (\r, \x1b[?25l/h hide-cursor, \x1b[2K clear-line). Spinner +
1526
1568
  # overwrite primitives must degrade cleanly when output is piped.
1527
1569
  TMP=$(mktmp)
1528
- printf 'QS-FAWZI-01\n3\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1570
+ printf 'QS-FAWZI-11\n3\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1529
1571
  # Look for any of: bare CR, hide-cursor (?25), clear-line (\x1b[2K).
1530
1572
  if [ -s "$TMP/log.txt" ] \
1531
1573
  && ! grep -q $'\r' "$TMP/log.txt" \
@@ -1538,7 +1580,7 @@ fi
1538
1580
 
1539
1581
  # 125. Final summary card includes the new "Targets" + "Time" rows
1540
1582
  TMP=$(mktmp)
1541
- printf 'QS-FAWZI-01\n3\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1583
+ printf 'QS-FAWZI-11\n3\n' | HOME="$TMP" $NODE "$INSTALL_JS" > "$TMP/log.txt" 2>&1
1542
1584
  CLEAN=$(strip_ansi < "$TMP/log.txt")
1543
1585
  if echo "$CLEAN" | grep -q "Targets" \
1544
1586
  && echo "$CLEAN" | grep -q "Claude Code · Codex" \
@@ -1646,7 +1688,7 @@ echo "--- v5.3.0 (Matt Pocock gaps: prd, hook-gen, parallel-interface) ---"
1646
1688
 
1647
1689
  # Re-install for v5.3 assertions (TMP from #99 may have v5.1 state)
1648
1690
  TMP=$(mktmp)
1649
- echo "QS-FAWZI-01" | HOME="$TMP" $NODE "$INSTALL_JS" >/dev/null 2>&1
1691
+ echo "QS-FAWZI-11" | HOME="$TMP" $NODE "$INSTALL_JS" >/dev/null 2>&1
1650
1692
 
1651
1693
  # 135-137. /qualia-prd removed in v5.8.0 (was deprecated, overlapped /qualia-discuss).
1652
1694
  # Assert non-existence so the framework cannot accidentally re-ship it.
@@ -1676,28 +1718,28 @@ else
1676
1718
  fail_case "qualia-feature missing after install"
1677
1719
  fi
1678
1720
 
1679
- # 138. qualia-hook-gen skill installs
1680
- if [ -f "$TMP/.claude/skills/qualia-hook-gen/SKILL.md" ]; then
1681
- pass "qualia-hook-gen skill installs"
1721
+ # 138. qualia-hook-gen is removed from source and retired from default install
1722
+ if [ ! -f "$TMP/.claude/skills/qualia-hook-gen/SKILL.md" ] \
1723
+ && [ ! -d "$FRAMEWORK_DIR/skills/qualia-hook-gen" ]; then
1724
+ pass "qualia-hook-gen removed from source and default install"
1682
1725
  else
1683
- fail_case "qualia-hook-gen SKILL.md missing after install"
1726
+ fail_case "qualia-hook-gen should be absent from source and install"
1684
1727
  fi
1685
1728
 
1686
- # 139. qualia-hook-gen documents the three enforcement patterns (block/rewrite/warn)
1687
- if grep -q "Block" "$TMP/.claude/skills/qualia-hook-gen/SKILL.md" \
1688
- && grep -q "Rewrite" "$TMP/.claude/skills/qualia-hook-gen/SKILL.md" \
1689
- && grep -q "Warn" "$TMP/.claude/skills/qualia-hook-gen/SKILL.md"; then
1690
- pass "qualia-hook-gen documents block/rewrite/warn patterns"
1729
+ # 139. hook generation knowledge moved out of slash-command source
1730
+ if grep -q "proxy_owner_approval_claim" "$FRAMEWORK_DIR/hooks/fawzi-approval-guard.js" \
1731
+ && grep -q "/api/v1/policy-events" "$FRAMEWORK_DIR/hooks/fawzi-approval-guard.js"; then
1732
+ pass "hook enforcement lives in runtime hooks, not qualia-hook-gen"
1691
1733
  else
1692
- fail_case "qualia-hook-gen missing one of block/rewrite/warn patterns"
1734
+ fail_case "runtime hook enforcement guard missing"
1693
1735
  fi
1694
1736
 
1695
- # 140. qualia-hook-gen mandates Node hooks (cross-platform), not .sh scripts
1696
- if grep -q "pure Node\|pure-node\|cross-platform" "$TMP/.claude/skills/qualia-hook-gen/SKILL.md" \
1697
- && grep -q "No \`.sh\`\|No \\.sh\|exit 0/2\|exit 2 to" "$TMP/.claude/skills/qualia-hook-gen/SKILL.md"; then
1698
- pass "qualia-hook-gen mandates pure-Node hooks (cross-platform discipline)"
1737
+ # 140. retired hook-gen behavior remains covered by Node hook files
1738
+ if find "$FRAMEWORK_DIR/hooks" -maxdepth 1 -name "*.js" -print | grep -q . \
1739
+ && ! find "$FRAMEWORK_DIR/hooks" -maxdepth 1 -name "*.sh" -print | grep -q .; then
1740
+ pass "runtime hooks are pure Node files"
1699
1741
  else
1700
- fail_case "qualia-hook-gen missing pure-Node mandate"
1742
+ fail_case "runtime hooks should remain pure Node"
1701
1743
  fi
1702
1744
 
1703
1745
  # 141. qualia-optimize SKILL.md adds Step 5b (parallel-interface design)
@@ -1862,13 +1904,63 @@ else
1862
1904
  fail_case "report-payload UUID pass-through failed" "$OUT"
1863
1905
  fi
1864
1906
 
1907
+ # 148b. work-packet links flow into report payloads
1908
+ TMP_PACKET=$(mktmp)
1909
+ OUT=$(FRAMEWORK_DIR="$FRAMEWORK_DIR" TMP_PACKET="$TMP_PACKET" $NODE <<'NODE' 2>&1
1910
+ const assert = require("assert/strict");
1911
+ const fs = require("fs");
1912
+ const path = require("path");
1913
+ const { buildPayload } = require(path.join(process.env.FRAMEWORK_DIR, "bin", "report-payload.js"));
1914
+ const { readLocalWorkPacket } = require(path.join(process.env.FRAMEWORK_DIR, "bin", "work-packet.js"));
1915
+
1916
+ const root = process.env.TMP_PACKET;
1917
+ const cwd = path.join(root, "project");
1918
+ const home = path.join(root, "home");
1919
+ fs.mkdirSync(path.join(cwd, ".planning"), { recursive: true });
1920
+ fs.mkdirSync(path.join(home, ".claude"), { recursive: true });
1921
+ fs.writeFileSync(path.join(home, ".claude", ".qualia-config.json"), JSON.stringify({ version: "test-version" }));
1922
+ fs.writeFileSync(path.join(cwd, ".planning", "tracking.json"), JSON.stringify({
1923
+ project: "acme-portal",
1924
+ project_id: "qs-acme-portal",
1925
+ erp_project_id: "7b5d3b4e-2b8a-4de4-91a1-9b2f3182f5ef",
1926
+ phase: 1,
1927
+ status: "built"
1928
+ }));
1929
+ fs.writeFileSync(path.join(cwd, ".planning", "work-packet.json"), JSON.stringify({
1930
+ id: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
1931
+ project_id: "7b5d3b4e-2b8a-4de4-91a1-9b2f3182f5ef",
1932
+ assignment_id: "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
1933
+ deadline_date: "2026-06-01",
1934
+ next_command: "/qualia-verify"
1935
+ }));
1936
+
1937
+ const packet = readLocalWorkPacket(cwd);
1938
+ assert.equal(packet.next_command, "/qualia-verify");
1939
+ const payload = buildPayload({
1940
+ cwd,
1941
+ home,
1942
+ env: { SUBMITTED_BY: "Fawzi Goussous", SUBMITTED_AT: "2026-05-21T01:30:00Z" },
1943
+ });
1944
+ assert.equal(payload.work_packet_id, "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa");
1945
+ assert.equal(payload.assignment_id, "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb");
1946
+ assert.equal(payload.assignment_deadline, "2026-06-01");
1947
+ NODE
1948
+ )
1949
+ EXIT=$?
1950
+ if [ "$EXIT" -eq 0 ]; then
1951
+ pass "work-packet links flow into report payloads"
1952
+ else
1953
+ fail_case "work-packet report payload link failed" "$OUT"
1954
+ fi
1955
+
1865
1956
  # 149. Installer ships the payload builder used by /qualia-report
1866
1957
  TMP_INSTALL=$(mktmp)
1867
- echo "QS-FAWZI-01" | HOME="$TMP_INSTALL" $NODE "$INSTALL_JS" > "$TMP_INSTALL/out.log" 2>&1
1958
+ echo "QS-FAWZI-11" | HOME="$TMP_INSTALL" $NODE "$INSTALL_JS" > "$TMP_INSTALL/out.log" 2>&1
1868
1959
  EXIT=$?
1869
1960
  if [ "$EXIT" -eq 0 ] \
1870
1961
  && [ -f "$TMP_INSTALL/.claude/bin/report-payload.js" ] \
1871
1962
  && [ -f "$TMP_INSTALL/.claude/bin/project-snapshot.js" ] \
1963
+ && [ -f "$TMP_INSTALL/.claude/bin/work-packet.js" ] \
1872
1964
  && grep -q "report-payload.js" "$TMP_INSTALL/.claude/skills/qualia-report/SKILL.md"; then
1873
1965
  pass "installer ships ERP report/snapshot helpers"
1874
1966
  else
@@ -1924,12 +2016,22 @@ fs.writeFileSync(path.join(cwd, ".planning", "tracking.json"), JSON.stringify({
1924
2016
  last_closed_milestone: 1
1925
2017
  }
1926
2018
  }));
2019
+ fs.writeFileSync(path.join(cwd, ".planning", "work-packet.json"), JSON.stringify({
2020
+ id: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
2021
+ project_id: "7b5d3b4e-2b8a-4de4-91a1-9b2f3182f5ef",
2022
+ assignment_id: "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
2023
+ deadline_date: "2026-06-01",
2024
+ next_command: "/qualia-verify"
2025
+ }));
1927
2026
 
1928
2027
  const snapshot = buildSnapshot({ cwd, home, now: "2026-05-21T00:00:00.000Z" });
1929
2028
  assert.equal(snapshot.snapshot_version, 1);
1930
2029
  assert.equal(snapshot.framework_version, "test-version");
1931
2030
  assert.equal(snapshot.identifiers.project_id, "qs-acme-portal");
1932
2031
  assert.equal(snapshot.identifiers.erp_project_id, "7b5d3b4e-2b8a-4de4-91a1-9b2f3182f5ef");
2032
+ assert.equal(snapshot.identifiers.work_packet_id, "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa");
2033
+ assert.equal(snapshot.identifiers.assignment_id, "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb");
2034
+ assert.equal(snapshot.identifiers.assignment_deadline, "2026-06-01");
1933
2035
  assert.equal(snapshot.project.progress_percent, 42);
1934
2036
  assert.equal(snapshot.current.gap_cycles, 1);
1935
2037
  assert.equal(snapshot.journey.total_milestones, 3);