@a-company/paradigm 3.44.0 → 5.3.3

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 (168) hide show
  1. package/dist/{accept-orchestration-ZUWQUHSK.js → accept-orchestration-GX2YRWM4.js} +5 -5
  2. package/dist/{add-VSPZ6FM4.js → add-FZRKEGH4.js} +1 -1
  3. package/dist/agent-HYKC2LAK.js +387 -0
  4. package/dist/agent-loader-SJPJJS33.js +36 -0
  5. package/dist/{agents-suggest-65SER5IS.js → agents-suggest-DNSYJ6IA.js} +1 -1
  6. package/dist/{aggregate-SV3VGEIL.js → aggregate-H57K7PNV.js} +1 -1
  7. package/dist/{assess-UHBDYIK7.js → assess-4WVXZLZQ.js} +2 -2
  8. package/dist/{auto-24ICVUH4.js → auto-QFS5NHQU.js} +1 -1
  9. package/dist/{beacon-3SJV4DAP.js → beacon-KXZXYQHX.js} +1 -1
  10. package/dist/{calibration-WWHK73WU.js → calibration-V46G7JTY.js} +2 -2
  11. package/dist/{check-OLI6AUS6.js → check-OWAIWV23.js} +1 -1
  12. package/dist/{chunk-RP6TZYGE.js → chunk-2IO7JAG2.js} +1 -1
  13. package/dist/chunk-2T6BTYBN.js +712 -0
  14. package/dist/{chunk-CDMAMDSG.js → chunk-5VKJBNJL.js} +13 -5
  15. package/dist/{chunk-KB4XJWE3.js → chunk-6N3JTACN.js} +98 -437
  16. package/dist/chunk-7N7GSU6K.js +34 -0
  17. package/dist/chunk-A2L4TSLZ.js +526 -0
  18. package/dist/{chunk-P7XSBJE3.js → chunk-ABVQGRF7.js} +1 -1
  19. package/dist/{chunk-HIKKOCXY.js → chunk-EI32ZBE6.js} +1 -1
  20. package/dist/{chunk-QIOCFXDQ.js → chunk-EKGMAM62.js} +1 -1
  21. package/dist/chunk-EZ3GOCYC.js +132 -0
  22. package/dist/chunk-GGMI6C2L.js +1075 -0
  23. package/dist/{chunk-DS5QY37M.js → chunk-GTR2TBIJ.js} +247 -15
  24. package/dist/{chunk-QDXI2DHR.js → chunk-J2JEQRT3.js} +1 -1
  25. package/dist/{chunk-AKIMFN6I.js → chunk-JASGXLK3.js} +2 -2
  26. package/dist/chunk-KVDYJLTC.js +121 -0
  27. package/dist/{chunk-J4E6K5MG.js → chunk-LSRABQIY.js} +25 -1
  28. package/dist/chunk-MCMOGQMU.js +145 -0
  29. package/dist/{chunk-ZXMDA7VB.js → chunk-PDX44BCA.js} +1 -6
  30. package/dist/{chunk-SOBTKFSP.js → chunk-S2HO5MLR.js} +5 -0
  31. package/dist/{chunk-2SKXFXIT.js → chunk-S3ORKP3V.js} +10 -15
  32. package/dist/{chunk-ZMQA6SCO.js → chunk-S6MZ2IEX.js} +628 -228
  33. package/dist/chunk-TAIJOFOE.js +124 -0
  34. package/dist/{chunk-FS3WTUHY.js → chunk-TXESEO7Y.js} +6 -6
  35. package/dist/{chunk-7COU5S2Z.js → chunk-VL67H5IC.js} +1 -1
  36. package/dist/{chunk-QWA26UNO.js → chunk-WQITYKHM.js} +7 -7
  37. package/dist/{chunk-MW5DMGBB.js → chunk-YMDLDELF.js} +114 -55
  38. package/dist/{claude-63ISJAZK.js → claude-FRRWJSTJ.js} +1 -1
  39. package/dist/{claude-cli-ABML5RHX.js → claude-cli-XJLK2X4L.js} +1 -1
  40. package/dist/{claude-code-JRLMRPTO.js → claude-code-HTBA4XRB.js} +1 -1
  41. package/dist/{claude-code-teams-CAJBEFIZ.js → claude-code-teams-T4SP24MD.js} +1 -1
  42. package/dist/{conductor-HLWYWUVH.js → conductor-PGPDVIVE.js} +1 -1
  43. package/dist/{config-schema-3YNIFJCJ.js → config-schema-EA4XALGG.js} +4 -2
  44. package/dist/{constellation-FAGT45TU.js → constellation-A26CCGQS.js} +1 -1
  45. package/dist/{context-audit-557EO6PK.js → context-audit-RLO3ETRP.js} +8 -5
  46. package/dist/{cost-XEBADYFT.js → cost-BGM32XJU.js} +1 -1
  47. package/dist/{cost-UD3WPEKZ.js → cost-VI46A4XL.js} +1 -1
  48. package/dist/{cursor-cli-QUOOF2N4.js → cursor-cli-JVEZGHWQ.js} +1 -1
  49. package/dist/{cursorrules-3TKZ4E4R.js → cursorrules-HLIKJJZT.js} +1 -1
  50. package/dist/decision-loader-WWCLIQPJ.js +20 -0
  51. package/dist/{delete-RRK4RL6Y.js → delete-KBRPQLPC.js} +2 -2
  52. package/dist/{diff-IP5CIARP.js → diff-RQLLNAFI.js} +5 -5
  53. package/dist/{discipline-5F5OVTXB.js → discipline-FA4OZXIS.js} +1 -1
  54. package/dist/{dist-UXWV4OKX.js → dist-34NA5RS5.js} +1 -1
  55. package/dist/{dist-5QE2BB2B-X6DYVSUL.js → dist-5QE2BB2B-5S3T6Y3T.js} +1 -1
  56. package/dist/{dist-CM3MVWWW.js → dist-77JDTVAY.js} +1 -0
  57. package/dist/{dist-POMVY6WP.js → dist-QK4SQAK7.js} +1 -1
  58. package/dist/{dist-3RVKEJRT.js → dist-TA6LSC2Q.js} +1 -1
  59. package/dist/docs-LVLRPBAW.js +155 -0
  60. package/dist/docs-PBZB7LYP.js +89 -0
  61. package/dist/{doctor-GKZJU7QG.js → doctor-ULBOHEIC.js} +3 -3
  62. package/dist/{drift-YGT4LJ7Q.js → drift-R5NRKFHI.js} +1 -1
  63. package/dist/{echo-A6HD5UP7.js → echo-O2LY7CC2.js} +1 -1
  64. package/dist/{edit-4CLNN5JG.js → edit-R2HNLMOG.js} +2 -2
  65. package/dist/event-25OJKDCE.js +31 -0
  66. package/dist/{export-T7CMMJIB.js → export-IWVL7XLF.js} +1 -1
  67. package/dist/{flow-UFMPVOEM.js → flow-CRRVV3O3.js} +2 -2
  68. package/dist/{global-HHUJSBG5.js → global-3NG5JXUB.js} +1 -1
  69. package/dist/graduate-USAWGBJM.js +160 -0
  70. package/dist/{graph-YYUXI3F7.js → graph-VHUMAAS6.js} +2 -2
  71. package/dist/{graph-server-ZPXRSGCW.js → graph-server-YL22VBBN.js} +1 -1
  72. package/dist/{habits-RG5SVKXP.js → habits-OL5NGPXO.js} +3 -3
  73. package/dist/{history-CETCSUCP.js → history-WOWC573W.js} +1 -1
  74. package/dist/{hooks-TCUHQMPF.js → hooks-HFWSCGPV.js} +2 -2
  75. package/dist/index.js +307 -184
  76. package/dist/{integrity-MK2OP5TA.js → integrity-IHO4FZTS.js} +1 -1
  77. package/dist/{integrity-checker-J7YXRTBT.js → integrity-checker-PSKJA5SB.js} +1 -0
  78. package/dist/journal-loader-5EYSBFFY.js +18 -0
  79. package/dist/{lint-HYWGS3JJ.js → lint-K6CJGGPH.js} +1 -1
  80. package/dist/{list-IUCYPGMK.js → list-4YK7QKFF.js} +1 -1
  81. package/dist/{list-BTLFHSRC.js → list-ENR7Q4CR.js} +2 -2
  82. package/dist/{lore-loader-VTEEZDX3.js → lore-loader-7NO6N6FT.js} +4 -1
  83. package/dist/{lore-server-NOOAHKJX.js → lore-server-UNJY5KC3.js} +1 -1
  84. package/dist/{manual-AFJ2J2V3.js → manual-G6FISID5.js} +1 -1
  85. package/dist/mcp.js +3954 -479
  86. package/dist/{migrate-FQVGQNXZ.js → migrate-LS45DNEV.js} +2 -2
  87. package/dist/{migrate-assessments-JP6Q5KME.js → migrate-assessments-RGH4O6IX.js} +2 -2
  88. package/dist/nomination-engine-Q4XSXFKT.js +40 -0
  89. package/dist/notebook-YWIYGEHV.js +155 -0
  90. package/dist/{orchestrate-A226N6FC.js → orchestrate-XZA33TJC.js} +5 -5
  91. package/dist/peers-DEOUIZM6.js +82 -0
  92. package/dist/persona-UHAHIVST.js +390 -0
  93. package/dist/{pipeline-3G2FRAKM.js → pipeline-L4HCSBGN.js} +1 -1
  94. package/dist/{platform-server-KHL6ZPPN.js → platform-server-PMD57BEG.js} +264 -18
  95. package/dist/{plugin-update-checker-HMRPGY5Z.js → plugin-update-checker-ELOEEQYS.js} +1 -0
  96. package/dist/{portal-check-FF5EKZE5.js → portal-check-NPYGII2D.js} +2 -2
  97. package/dist/{portal-compliance-VU4NIFEN.js → portal-compliance-J7DGAPFX.js} +2 -2
  98. package/dist/{probe-7JK7IDNI.js → probe-MHL5HQZ2.js} +3 -3
  99. package/dist/{promote-XO63XMAN.js → promote-F6ZYZZAL.js} +2 -2
  100. package/dist/{providers-YNFSL6HK.js → providers-GK7PB2OL.js} +2 -2
  101. package/dist/{quiz-I75NU2QQ.js → quiz-M66SC7F7.js} +1 -1
  102. package/dist/{record-46CLR4OG.js → record-RA4WR2BO.js} +2 -2
  103. package/dist/{reindex-WIJMCJ4A.js → reindex-HRA2AUS6.js} +3 -2
  104. package/dist/{remember-4EUZKIIB.js → remember-HBWJ655S.js} +1 -1
  105. package/dist/{retag-KC4JVRLE.js → retag-3OLCVDEQ.js} +2 -2
  106. package/dist/{review-Q7M4CRB5.js → review-27ATYTD2.js} +2 -2
  107. package/dist/review-57QMURZV.js +334 -0
  108. package/dist/{ripple-RI3LOT6R.js → ripple-JPBXP5I3.js} +1 -1
  109. package/dist/{sentinel-UOIGJWHH.js → sentinel-4XIG4STA.js} +2 -2
  110. package/dist/{sentinel-bridge-APDXYAZS.js → sentinel-bridge-MDUXTQRL.js} +2 -2
  111. package/dist/{serve-JVXSRSUB.js → serve-FLTFTM3P.js} +2 -2
  112. package/dist/{serve-22A4XOIG.js → serve-INL7SNBK.js} +2 -2
  113. package/dist/{serve-2YJ6D2Y6.js → serve-KBSE36PL.js} +4 -4
  114. package/dist/{server-JV6UFGWZ.js → server-54SKYFFY.js} +2 -2
  115. package/dist/{server-RDLQ3DK7.js → server-XUOIO7E6.js} +1 -1
  116. package/dist/{setup-YNZJQLW7.js → setup-EDS27WUR.js} +1 -1
  117. package/dist/{setup-M2ZKLKNN.js → setup-KO5AFC4K.js} +2 -2
  118. package/dist/{shift-LNMKFYLR.js → shift-VFG23DLA.js} +16 -16
  119. package/dist/{show-P7GYO43X.js → show-5PV5KFJE.js} +2 -2
  120. package/dist/{show-PKZMYKRN.js → show-NQKYX6WQ.js} +1 -1
  121. package/dist/{snapshot-Y3COXK4T.js → snapshot-BK4RBPCG.js} +1 -1
  122. package/dist/{spawn-SSXZX45U.js → spawn-AW6GDECS.js} +3 -3
  123. package/dist/{status-KLHALGW4.js → status-WGIAQODY.js} +1 -1
  124. package/dist/{summary-5NQNOD3F.js → summary-NIRABMF5.js} +2 -2
  125. package/dist/{sweep-EZU3GU6S.js → sweep-QMHNSIY5.js} +2 -2
  126. package/dist/{switch-WYUMVNA5.js → switch-6EJPZDIA.js} +1 -1
  127. package/dist/{symphony-EYRGGVNE.js → symphony-4OCY36AI.js} +350 -29
  128. package/dist/{symphony-QWOEKZMC.js → symphony-B75X2MME.js} +20 -2
  129. package/dist/symphony-peers-2ZQYLRNI.js +34 -0
  130. package/dist/symphony-peers-OL7F6M5S.js +121 -0
  131. package/dist/symphony-relay-UJYUXN65.js +710 -0
  132. package/dist/{sync-ZM4Q3R4U.js → sync-VEHUH4OA.js} +3 -3
  133. package/dist/{sync-llms-JIPP3XX4.js → sync-llms-YHCFIE6X.js} +2 -2
  134. package/dist/{task-loader-7M2FCBX6.js → task-loader-LDYWQSLM.js} +1 -0
  135. package/dist/{team-HGLJXWQG.js → team-7HG7XK5C.js} +6 -6
  136. package/dist/{test-WTR5Q33E.js → test-566CP5KC.js} +1 -1
  137. package/dist/{thread-3WM7KKID.js → thread-N754I4D5.js} +1 -1
  138. package/dist/{timeline-ANC7LVDL.js → timeline-M3CICQFE.js} +2 -2
  139. package/dist/{triage-IZ4MDYNB.js → triage-HHYGT3HY.js} +1 -1
  140. package/dist/{tutorial-GC6QL4US.js → tutorial-KD22SUNO.js} +1 -1
  141. package/dist/university-content/courses/.purpose +66 -0
  142. package/dist/university-content/courses/para-401.json +146 -0
  143. package/dist/university-content/courses/para-501.json +151 -0
  144. package/dist/university-content/courses/para-601.json +608 -0
  145. package/dist/university-content/plsat/.purpose +6 -0
  146. package/dist/university-content/plsat/v2.0.json +2 -2
  147. package/dist/university-content/plsat/v3.0.json +563 -3
  148. package/dist/university-content/reference.json +91 -0
  149. package/dist/{upgrade-ANX3LVSA.js → upgrade-H5PF32BW.js} +2 -2
  150. package/dist/{validate-GD5XWILV.js → validate-CNKEKO6A.js} +1 -1
  151. package/dist/{validate-ITC5D6QG.js → validate-MB5ULIHS.js} +1 -1
  152. package/dist/{validate-ZVPNN4FL.js → validate-QH3LADM6.js} +1 -1
  153. package/dist/{watch-X64UK7K4.js → watch-2TKP5PVL.js} +3 -3
  154. package/dist/{watch-ERBEJUJW.js → watch-ZF4ML6CD.js} +2 -2
  155. package/dist/{wisdom-L2WC7J62.js → wisdom-AATMGNFA.js} +1 -1
  156. package/dist/work-log-loader-5L45XNYZ.js +14 -0
  157. package/dist/{workspace-UIUTHZTD.js → workspace-6E6OSRNU.js} +4 -4
  158. package/package.json +1 -1
  159. package/platform-ui/dist/assets/DocsSection-ByAgPzWV.js +1 -0
  160. package/platform-ui/dist/assets/DocsSection-CjdO6R-u.css +1 -0
  161. package/platform-ui/dist/assets/{GitSection-BD3Ze06e.js → GitSection-BLovj9yT.js} +1 -1
  162. package/platform-ui/dist/assets/{GraphSection-SglITfSs.js → GraphSection-C5PCPUFl.js} +1 -1
  163. package/platform-ui/dist/assets/{LoreSection-bR5Km4Fd.js → LoreSection-BftejTla.js} +1 -1
  164. package/platform-ui/dist/assets/{SentinelSection-QSpAZArG.js → SentinelSection-CnYcasN7.js} +1 -1
  165. package/platform-ui/dist/assets/{SymphonySection-CobYJgvg.js → SymphonySection-BpmqCHeK.js} +1 -1
  166. package/platform-ui/dist/assets/{index-DbxeSMkV.js → index-G9JnWEs_.js} +10 -10
  167. package/platform-ui/dist/index.html +1 -1
  168. package/dist/dist-PSF5CP4I.js +0 -7294
@@ -16,11 +16,16 @@ var COMMON_HOOK = `#!/bin/sh
16
16
  # CWD \u2014 Project root directory (already cd'd into)
17
17
  # MODIFIED \u2014 Output of \`git diff --name-only HEAD\`
18
18
  #
19
+ # Caller may set:
20
+ # PARADIGM_AUTO_FIX \u2014 Set to "1" to auto-fix trivial violations (missing .purpose stubs, missing lore)
21
+ #
19
22
  # Sets:
20
23
  # VIOLATIONS \u2014 Newline-separated violation messages
21
24
  # VIOLATION_COUNT \u2014 Number of violations
22
25
  # ADVISORY \u2014 Non-blocking advisory text
23
26
  # SOURCE_COUNT \u2014 Number of modified source files
27
+ # AUTO_FIXED \u2014 Newline-separated auto-fix actions taken
28
+ # AUTO_FIX_COUNT \u2014 Number of auto-fixes applied
24
29
  #
25
30
  # Checks:
26
31
  # 1. Source files modified without .purpose updates (threshold: 2+)
@@ -37,6 +42,9 @@ var COMMON_HOOK = `#!/bin/sh
37
42
 
38
43
  VIOLATIONS=""
39
44
  VIOLATION_COUNT=0
45
+ AUTO_FIXED=""
46
+ AUTO_FIX_COUNT=0
47
+ PARADIGM_AUTO_FIX="\${PARADIGM_AUTO_FIX:-0}"
40
48
 
41
49
  # --- Check 1: Source files modified without .purpose updates ---
42
50
  SOURCE_COUNT=0
@@ -95,11 +103,28 @@ for file in $MODIFIED; do
95
103
  done
96
104
 
97
105
  if [ -n "$DIRS_WITHOUT_PURPOSE" ]; then
98
- VIOLATIONS="$VIOLATIONS
106
+ if [ "$PARADIGM_AUTO_FIX" = "1" ]; then
107
+ # Auto-fix: create stub .purpose files for directories missing them
108
+ for dir in $DIRS_WITHOUT_PURPOSE; do
109
+ dir_basename=$(basename "$dir")
110
+ cat > "$dir/.purpose" <<PURPOSEEOF
111
+ # Auto-generated .purpose stub \u2014 update with real descriptions
112
+ components:
113
+ $dir_basename:
114
+ description: "TODO: describe this component"
115
+ tags: []
116
+ PURPOSEEOF
117
+ AUTO_FIXED="$AUTO_FIXED
118
+ - Created stub .purpose in $dir (update descriptions)"
119
+ AUTO_FIX_COUNT=$((AUTO_FIX_COUNT + 1))
120
+ done
121
+ else
122
+ VIOLATIONS="$VIOLATIONS
99
123
  - These directories have modified source files but no .purpose file anywhere in their path:
100
124
  $DIRS_WITHOUT_PURPOSE
101
125
  Create a .purpose file using paradigm_purpose_init + paradigm_purpose_add_component."
102
- VIOLATION_COUNT=$((VIOLATION_COUNT + 1))
126
+ VIOLATION_COUNT=$((VIOLATION_COUNT + 1))
127
+ fi
103
128
  fi
104
129
 
105
130
  # --- Check 3: Route patterns added without portal.yaml ---
@@ -252,11 +277,46 @@ if [ "$SOURCE_COUNT" -ge 3 ] && [ -d ".paradigm/lore" ]; then
252
277
  fi
253
278
 
254
279
  if [ "$LORE_RECORDED" = false ]; then
255
- VIOLATIONS="$VIOLATIONS
280
+ if [ "$PARADIGM_AUTO_FIX" = "1" ]; then
281
+ # Auto-fix: create a stub lore entry with modified file info
282
+ TODAY=$(date -u +"%Y-%m-%d" 2>/dev/null || date +"%Y-%m-%d")
283
+ LORE_TIMESTAMP=$(date -u +"%H%M%S" 2>/dev/null || date +"%H%M%S")
284
+ LORE_DIR=".paradigm/lore/entries/$TODAY"
285
+ mkdir -p "$LORE_DIR" 2>/dev/null
286
+ LORE_ID="L-\${TODAY}-auto-\${LORE_TIMESTAMP}"
287
+ LORE_FILE="$LORE_DIR/\${LORE_ID}.yaml"
288
+
289
+ # Extract symbols from modified file paths (directory basenames as component names)
290
+ LORE_SYMBOLS=""
291
+ for file in $MODIFIED; do
292
+ case "$file" in
293
+ .paradigm/*|*.md|*.lock|*.log|.gitignore|.env*|*.json|*.purpose|portal.yaml) continue ;;
294
+ esac
295
+ sym_dir=$(basename "$(dirname "$file")")
296
+ case "$LORE_SYMBOLS" in
297
+ *"#$sym_dir"*) ;;
298
+ *) LORE_SYMBOLS="$LORE_SYMBOLS \\"#$sym_dir\\"" ;;
299
+ esac
300
+ done
301
+
302
+ cat > "$LORE_FILE" <<LOREEOF
303
+ id: "$LORE_ID"
304
+ type: agent-session
305
+ title: "Auto-recorded session \u2014 $SOURCE_COUNT files modified"
306
+ summary: "Session modified $SOURCE_COUNT source files. Auto-recorded by stop hook."
307
+ symbols_touched: [$(echo $LORE_SYMBOLS | sed 's/^ //')]
308
+ timestamp: "$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date +"%Y-%m-%dT%H:%M:%SZ")"
309
+ LOREEOF
310
+ AUTO_FIXED="$AUTO_FIXED
311
+ - Created stub lore entry $LORE_ID (update with real summary)"
312
+ AUTO_FIX_COUNT=$((AUTO_FIX_COUNT + 1))
313
+ else
314
+ VIOLATIONS="$VIOLATIONS
256
315
  - You modified $SOURCE_COUNT source files but recorded no lore entry.
257
316
  Record your session: paradigm_lore_record (MCP) or paradigm lore record (CLI).
258
317
  Include: type, title, summary, and symbols_touched."
259
- VIOLATION_COUNT=$((VIOLATION_COUNT + 1))
318
+ VIOLATION_COUNT=$((VIOLATION_COUNT + 1))
319
+ fi
260
320
  fi
261
321
  fi
262
322
 
@@ -350,11 +410,28 @@ if [ -f "$CONFIG_FILE" ]; then
350
410
  fi
351
411
 
352
412
  if [ -n "$MISSING_REQUIRED" ]; then
353
- VIOLATIONS="$VIOLATIONS
413
+ if [ "$PARADIGM_AUTO_FIX" = "1" ]; then
414
+ # Auto-fix: create stub .purpose files for required patterns
415
+ for dir in $MISSING_REQUIRED; do
416
+ dir_basename=$(basename "$dir")
417
+ cat > "$dir/.purpose" <<PURPOSEEOF
418
+ # Auto-generated .purpose stub (purpose-required) \u2014 update with real descriptions
419
+ components:
420
+ $dir_basename:
421
+ description: "TODO: describe this component"
422
+ tags: []
423
+ PURPOSEEOF
424
+ AUTO_FIXED="$AUTO_FIXED
425
+ - Created stub .purpose in $dir (purpose-required pattern)"
426
+ AUTO_FIX_COUNT=$((AUTO_FIX_COUNT + 1))
427
+ done
428
+ else
429
+ VIOLATIONS="$VIOLATIONS
354
430
  - These directories match purpose-required patterns but have no .purpose file:
355
431
  $MISSING_REQUIRED
356
432
  Create .purpose files: paradigm_purpose_init + paradigm_purpose_add_component."
357
- VIOLATION_COUNT=$((VIOLATION_COUNT + 1))
433
+ VIOLATION_COUNT=$((VIOLATION_COUNT + 1))
434
+ fi
358
435
  fi
359
436
  fi
360
437
 
@@ -406,6 +483,54 @@ if [ -f "portal.yaml" ]; then
406
483
  fi
407
484
  fi
408
485
  fi
486
+
487
+ # --- Check 12: Graduation failure tracking ---
488
+ # When violations occur for graduated habits, record failures for auto-demotion.
489
+ if [ "$VIOLATION_COUNT" -gt 0 ] && [ -f ".paradigm/graduation.yaml" ]; then
490
+ GRAD_FAILURES_DIR=".paradigm/.graduation-failures"
491
+ mkdir -p "$GRAD_FAILURES_DIR" 2>/dev/null
492
+
493
+ # Map violations to graduated habit IDs
494
+ # Check 1/2/5 \u2192 purpose-coverage, Check 3/11 \u2192 gates-for-routes, Check 7 \u2192 record-lore-for-significant
495
+ NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date +%Y-%m-%dT%H:%M:%SZ)
496
+
497
+ # Purpose coverage violations \u2192 purpose-coverage habit
498
+ if echo "$VIOLATIONS" | grep -q "source file.*without .purpose\\|missing .purpose\\|purpose.*stale" 2>/dev/null; then
499
+ if grep -q "purpose-coverage" ".paradigm/graduation.yaml" 2>/dev/null && grep -A1 "purpose-coverage" ".paradigm/graduation.yaml" | grep -q "tier: hook" 2>/dev/null; then
500
+ echo "$NOW" >> "$GRAD_FAILURES_DIR/purpose-coverage"
501
+ fi
502
+ fi
503
+
504
+ # Portal gate violations \u2192 gates-for-routes habit
505
+ if echo "$VIOLATIONS" | grep -q "portal.yaml\\|gate.*undeclared\\|gate.*not declared" 2>/dev/null; then
506
+ if grep -q "gates-for-routes" ".paradigm/graduation.yaml" 2>/dev/null && grep -A1 "gates-for-routes" ".paradigm/graduation.yaml" | grep -q "tier: hook" 2>/dev/null; then
507
+ echo "$NOW" >> "$GRAD_FAILURES_DIR/gates-for-routes"
508
+ fi
509
+ fi
510
+
511
+ # Lore entry violations \u2192 record-lore-for-significant habit
512
+ if echo "$VIOLATIONS" | grep -q "lore entry expected\\|no lore" 2>/dev/null; then
513
+ if grep -q "record-lore-for-significant" ".paradigm/graduation.yaml" 2>/dev/null && grep -A1 "record-lore-for-significant" ".paradigm/graduation.yaml" | grep -q "tier: hook" 2>/dev/null; then
514
+ echo "$NOW" >> "$GRAD_FAILURES_DIR/record-lore-for-significant"
515
+ fi
516
+ fi
517
+
518
+ # Count recent failures and emit advisory if approaching demotion threshold
519
+ for fail_file in "$GRAD_FAILURES_DIR"/*; do
520
+ [ -f "$fail_file" ] || continue
521
+ habit_id=$(basename "$fail_file")
522
+ fail_count=$(wc -l < "$fail_file" | tr -d ' ')
523
+ if [ "$fail_count" -ge 3 ]; then
524
+ ADVISORY="$ADVISORY
525
+ - Graduated habit '$habit_id' has $fail_count failures \u2014 auto-demotion triggered.
526
+ Run paradigm_graduate_status to review tier changes."
527
+ elif [ "$fail_count" -ge 2 ]; then
528
+ ADVISORY="$ADVISORY
529
+ - Graduated habit '$habit_id' has $fail_count failures (demotion at 3).
530
+ Fix the underlying issue or it will be demoted to habit tier."
531
+ fi
532
+ done
533
+ fi
409
534
  `;
410
535
  var CLAUDE_CODE_STOP_HOOK = `#!/bin/sh
411
536
  # Paradigm Claude Code Stop Hook (v2)
@@ -441,8 +566,9 @@ cd "$CWD" || exit 0
441
566
  # Get modified files (uncommitted changes)
442
567
  MODIFIED=$(git diff --name-only HEAD 2>/dev/null)
443
568
  if [ -z "$MODIFIED" ]; then
444
- # Clean up pending-review on pass
569
+ # Clean up session markers on pass (no modifications)
445
570
  rm -f ".paradigm/.pending-review"
571
+ rm -f ".paradigm/.session-started"
446
572
  exit 0
447
573
  fi
448
574
 
@@ -450,8 +576,19 @@ fi
450
576
  SCRIPT_DIR=$(dirname "$0")
451
577
  . "$SCRIPT_DIR/paradigm-common.sh"
452
578
 
579
+ # --- Report auto-fixes if any ---
580
+ if [ "$AUTO_FIX_COUNT" -gt 0 ]; then
581
+ echo "" >&2
582
+ echo "[paradigm] Auto-fixed $AUTO_FIX_COUNT issue(s):" >&2
583
+ echo "$AUTO_FIXED" >&2
584
+ fi
585
+
453
586
  # --- Final verdict ---
454
587
  if [ "$VIOLATION_COUNT" -gt 0 ]; then
588
+ # Emit compliance-violation event (fire-and-forget)
589
+ if command -v paradigm >/dev/null 2>&1; then
590
+ paradigm event emit --type compliance-violation --source stop-hook --severity error --context "Stop hook: $VIOLATION_COUNT violation(s)" &
591
+ fi
455
592
  echo "" >&2
456
593
  echo "Paradigm compliance check failed ($VIOLATION_COUNT violation(s)):" >&2
457
594
  echo "$VIOLATIONS" >&2
@@ -468,6 +605,8 @@ if [ "$VIOLATION_COUNT" -gt 0 ]; then
468
605
  echo " 4. paradigm_reindex \u2014 rebuild indexes after updates" >&2
469
606
  echo " 5. paradigm_lore_record \u2014 record session lore entry" >&2
470
607
  echo " 6. paradigm_habits_check \u2014 evaluate habit compliance" >&2
608
+ echo "" >&2
609
+ echo "Tip: Set PARADIGM_AUTO_FIX=1 to auto-fix trivial violations (missing .purpose stubs, missing lore)." >&2
471
610
  exit 2
472
611
  fi
473
612
 
@@ -478,9 +617,26 @@ if [ -n "$ADVISORY" ]; then
478
617
  echo "$ADVISORY" >&2
479
618
  fi
480
619
 
481
- # Clean up pending-review on pass
620
+ # Auto-demote graduated habits with 3+ failures
621
+ if [ -d ".paradigm/.graduation-failures" ]; then
622
+ for fail_file in .paradigm/.graduation-failures/*; do
623
+ [ -f "$fail_file" ] || continue
624
+ habit_id=$(basename "$fail_file")
625
+ fail_count=$(wc -l < "$fail_file" | tr -d ' ')
626
+ if [ "$fail_count" -ge 3 ]; then
627
+ if command -v paradigm >/dev/null 2>&1; then
628
+ paradigm graduate demote "$habit_id" --cooldown 14 2>/dev/null || true
629
+ fi
630
+ rm -f "$fail_file"
631
+ echo "[paradigm] Auto-demoted '$habit_id' after $fail_count failures." >&2
632
+ fi
633
+ done
634
+ fi
635
+
636
+ # Clean up session markers on pass
482
637
  rm -f ".paradigm/.pending-review"
483
638
  rm -f ".paradigm/.habits-blocking"
639
+ rm -f ".paradigm/.session-started"
484
640
 
485
641
  exit 0
486
642
  `;
@@ -493,17 +649,23 @@ var CLAUDE_CODE_POSTWRITE_HOOK = `#!/bin/sh
493
649
  #
494
650
  # Hook type: PostToolUse (matcher: Edit,Write)
495
651
  # Exit 0 always (never blocks \u2014 advisory only)
652
+ #
653
+ # NOTE: stdin JSON can be 8KB+ (tool_response includes full file contents).
654
+ # Using echo "$INPUT" | jq corrupts the JSON via shell string handling.
655
+ # Fix: write stdin to temp file, use jq < file for all extractions.
496
656
 
497
- # Read JSON from stdin (hook input)
498
- INPUT=$(cat)
657
+ # Save stdin to temp file \u2014 avoids echo corruption on large JSON
658
+ TMPINPUT=$(mktemp)
659
+ trap 'rm -f "$TMPINPUT"' EXIT
660
+ cat > "$TMPINPUT"
499
661
 
500
662
  # Extract the file path from tool_input
501
663
  if command -v jq >/dev/null 2>&1; then
502
- FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.filePath // empty' 2>/dev/null)
664
+ FILE_PATH=$(jq -r '.tool_input.file_path // .tool_input.filePath // empty' < "$TMPINPUT" 2>/dev/null)
503
665
  else
504
- FILE_PATH=$(echo "$INPUT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"file_path"[[:space:]]*:[[:space:]]*"//' | sed 's/"$//')
666
+ FILE_PATH=$(grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' "$TMPINPUT" | head -1 | sed 's/.*"file_path"[[:space:]]*:[[:space:]]*"//' | sed 's/"$//')
505
667
  if [ -z "$FILE_PATH" ]; then
506
- FILE_PATH=$(echo "$INPUT" | grep -o '"filePath"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"filePath"[[:space:]]*:[[:space:]]*"//' | sed 's/"$//')
668
+ FILE_PATH=$(grep -o '"filePath"[[:space:]]*:[[:space:]]*"[^"]*"' "$TMPINPUT" | head -1 | sed 's/.*"filePath"[[:space:]]*:[[:space:]]*"//' | sed 's/"$//')
507
669
  fi
508
670
  fi
509
671
 
@@ -511,6 +673,16 @@ if [ -z "$FILE_PATH" ]; then
511
673
  exit 0
512
674
  fi
513
675
 
676
+ # Extract cwd from input
677
+ if command -v jq >/dev/null 2>&1; then
678
+ CWD=$(jq -r '.cwd // empty' < "$TMPINPUT" 2>/dev/null)
679
+ else
680
+ CWD=$(grep -o '"cwd"[[:space:]]*:[[:space:]]*"[^"]*"' "$TMPINPUT" | sed 's/.*"cwd"[[:space:]]*:[[:space:]]*"//' | sed 's/"$//')
681
+ fi
682
+ if [ -n "$CWD" ]; then
683
+ cd "$CWD" || exit 0
684
+ fi
685
+
514
686
  # Skip non-source files
515
687
  case "$FILE_PATH" in
516
688
  *.purpose|portal.yaml|*.md|*.lock|*.log|*.json|*.yaml|*.yml|.gitignore|.env*) exit 0 ;;
@@ -526,6 +698,15 @@ if [ ! -d ".paradigm" ]; then
526
698
  exit 0
527
699
  fi
528
700
 
701
+ # Pseudo-session-start: first edit of session emits one-time guidance
702
+ if [ ! -f ".paradigm/.session-started" ]; then
703
+ PREV_PENDING=$(cat .paradigm/.pending-review 2>/dev/null | wc -l | tr -d ' ')
704
+ if [ "$PREV_PENDING" -gt 0 ] 2>/dev/null; then
705
+ echo "[paradigm] Session started. $PREV_PENDING uncovered edit(s) from last session." >&2
706
+ fi
707
+ touch ".paradigm/.session-started"
708
+ fi
709
+
529
710
  # Convert to relative path (strip project root prefix)
530
711
  PROJECT_ROOT="$(pwd)"
531
712
  REL_PATH="$FILE_PATH"
@@ -538,6 +719,11 @@ case "$REL_PATH" in
538
719
  /*) exit 0 ;;
539
720
  esac
540
721
 
722
+ # Emit file-modified event (fire-and-forget)
723
+ if command -v paradigm >/dev/null 2>&1; then
724
+ paradigm event emit --type file-modified --source post-write-hook --path "$REL_PATH" &
725
+ fi
726
+
541
727
  # Track: append to .paradigm/.pending-review (deduplicated)
542
728
  PENDING_FILE=".paradigm/.pending-review"
543
729
  if [ -f "$PENDING_FILE" ]; then
@@ -581,6 +767,11 @@ elif [ "$PENDING_COUNT" -gt 0 ] && [ "$((PENDING_COUNT % 3))" -eq 0 ]; then
581
767
  echo " The stop hook WILL BLOCK if .purpose files aren't updated." >&2
582
768
  fi
583
769
 
770
+ # Context budget heuristic: suggest handoff check at high edit counts
771
+ if [ "$PENDING_COUNT" -ge 30 ]; then
772
+ echo "[paradigm] ~$PENDING_COUNT edits this session. Consider preparing handoff." >&2
773
+ fi
774
+
584
775
  exit 0
585
776
  `;
586
777
  var CLAUDE_CODE_PRECOMMIT_HOOK = `#!/bin/sh
@@ -784,8 +975,9 @@ fi
784
975
  # Get modified files (uncommitted changes)
785
976
  MODIFIED=$(git diff --name-only HEAD 2>/dev/null)
786
977
  if [ -z "$MODIFIED" ]; then
787
- # Clean up pending-review on pass
978
+ # Clean up session markers on pass (no modifications)
788
979
  rm -f ".paradigm/.pending-review"
980
+ rm -f ".paradigm/.session-started"
789
981
  exit 0
790
982
  fi
791
983
 
@@ -793,6 +985,13 @@ fi
793
985
  SCRIPT_DIR=$(dirname "$0")
794
986
  . "$SCRIPT_DIR/paradigm-common.sh"
795
987
 
988
+ # --- Report auto-fixes if any ---
989
+ if [ "$AUTO_FIX_COUNT" -gt 0 ]; then
990
+ echo "" >&2
991
+ echo "[paradigm] Auto-fixed $AUTO_FIX_COUNT issue(s):" >&2
992
+ echo "$AUTO_FIXED" >&2
993
+ fi
994
+
796
995
  # --- Final verdict ---
797
996
  if [ "$VIOLATION_COUNT" -gt 0 ]; then
798
997
  echo "" >&2
@@ -811,6 +1010,8 @@ if [ "$VIOLATION_COUNT" -gt 0 ]; then
811
1010
  echo " 4. paradigm_reindex \u2014 rebuild indexes after updates" >&2
812
1011
  echo " 5. paradigm_lore_record \u2014 record session lore entry" >&2
813
1012
  echo " 6. paradigm_habits_check \u2014 evaluate habit compliance" >&2
1013
+ echo "" >&2
1014
+ echo "Tip: Set PARADIGM_AUTO_FIX=1 to auto-fix trivial violations (missing .purpose stubs, missing lore)." >&2
814
1015
 
815
1016
  # Output followup_message JSON to stdout for Cursor's compliance loop.
816
1017
  # Cursor auto-submits this as the next user message, creating a retry loop.
@@ -828,10 +1029,27 @@ if [ -n "$ADVISORY" ]; then
828
1029
  echo "$ADVISORY" >&2
829
1030
  fi
830
1031
 
831
- # Clean up pending-review and loop guard on pass
1032
+ # Auto-demote graduated habits with 3+ failures
1033
+ if [ -d ".paradigm/.graduation-failures" ]; then
1034
+ for fail_file in .paradigm/.graduation-failures/*; do
1035
+ [ -f "$fail_file" ] || continue
1036
+ habit_id=$(basename "$fail_file")
1037
+ fail_count=$(wc -l < "$fail_file" | tr -d ' ')
1038
+ if [ "$fail_count" -ge 3 ]; then
1039
+ if command -v paradigm >/dev/null 2>&1; then
1040
+ paradigm graduate demote "$habit_id" --cooldown 14 2>/dev/null || true
1041
+ fi
1042
+ rm -f "$fail_file"
1043
+ echo "[paradigm] Auto-demoted '$habit_id' after $fail_count failures." >&2
1044
+ fi
1045
+ done
1046
+ fi
1047
+
1048
+ # Clean up session markers and loop guard on pass
832
1049
  rm -f ".paradigm/.pending-review"
833
1050
  rm -f ".paradigm/.habits-blocking"
834
1051
  rm -f ".paradigm/.stop-hook-active"
1052
+ rm -f ".paradigm/.session-started"
835
1053
 
836
1054
  exit 0
837
1055
  `;
@@ -1166,6 +1384,15 @@ fi
1166
1384
 
1167
1385
  cd "$CWD" || exit 0
1168
1386
 
1387
+ # Pseudo-session-start: first edit of session emits one-time guidance
1388
+ if [ ! -f ".paradigm/.session-started" ]; then
1389
+ PREV_PENDING=$(cat .paradigm/.pending-review 2>/dev/null | wc -l | tr -d ' ')
1390
+ if [ "$PREV_PENDING" -gt 0 ] 2>/dev/null; then
1391
+ echo "[paradigm] Session started. $PREV_PENDING uncovered edit(s) from last session." >&2
1392
+ fi
1393
+ touch ".paradigm/.session-started"
1394
+ fi
1395
+
1169
1396
  # Convert to relative path
1170
1397
  REL_PATH="$FILE_PATH"
1171
1398
  case "$FILE_PATH" in
@@ -1230,6 +1457,11 @@ elif [ "$PENDING_COUNT" -gt 0 ] && [ "$((PENDING_COUNT % 3))" -eq 0 ]; then
1230
1457
  echo " The stop hook WILL BLOCK if .purpose files aren't updated." >&2
1231
1458
  fi
1232
1459
 
1460
+ # Context budget heuristic: suggest handoff check at high edit counts
1461
+ if [ "$PENDING_COUNT" -ge 30 ]; then
1462
+ echo "[paradigm] ~$PENDING_COUNT edits this session. Consider preparing handoff." >&2
1463
+ fi
1464
+
1233
1465
  exit 0
1234
1466
  `;
1235
1467
 
@@ -10,7 +10,7 @@ async function graphCommand(path, options) {
10
10
  const shouldOpen = options.open !== false;
11
11
  console.log(chalk.cyan("\nStarting Symbol Graph...\n"));
12
12
  try {
13
- const { startGraphServer } = await import("./graph-server-ZPXRSGCW.js");
13
+ const { startGraphServer } = await import("./graph-server-YL22VBBN.js");
14
14
  console.log(chalk.gray(`Project: ${projectDir}`));
15
15
  console.log(chalk.gray(`Port: ${port}`));
16
16
  console.log();
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  indexCommand
4
- } from "./chunk-7COU5S2Z.js";
4
+ } from "./chunk-VL67H5IC.js";
5
5
  import {
6
6
  getDefaultPremiseContent
7
7
  } from "./chunk-ZGUAAVMA.js";
@@ -19,7 +19,7 @@ import {
19
19
  detectIDE,
20
20
  loadParadigmFiles,
21
21
  syncToIDE
22
- } from "./chunk-KB4XJWE3.js";
22
+ } from "./chunk-6N3JTACN.js";
23
23
  import {
24
24
  log
25
25
  } from "./chunk-4NCFWYGG.js";
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+
3
+ // ../paradigm-mcp/src/utils/symphony-peers.ts
4
+ import * as fs from "fs";
5
+ import * as path from "path";
6
+ import * as os from "os";
7
+ import * as crypto from "crypto";
8
+ var SCORE_DIR = path.join(os.homedir(), ".paradigm", "score");
9
+ var PEERS_FILE = path.join(SCORE_DIR, "peers.json");
10
+ var PAIRING_TTL_MS = 5 * 60 * 1e3;
11
+ function loadPeers() {
12
+ try {
13
+ if (!fs.existsSync(PEERS_FILE)) return [];
14
+ const content = fs.readFileSync(PEERS_FILE, "utf-8");
15
+ const parsed = JSON.parse(content);
16
+ if (!Array.isArray(parsed)) return [];
17
+ return parsed;
18
+ } catch {
19
+ return [];
20
+ }
21
+ }
22
+ function savePeers(peers) {
23
+ if (!fs.existsSync(SCORE_DIR)) {
24
+ fs.mkdirSync(SCORE_DIR, { recursive: true });
25
+ }
26
+ fs.writeFileSync(PEERS_FILE, JSON.stringify(peers, null, 2), { mode: 384 });
27
+ }
28
+ function findPeer(id) {
29
+ const peers = loadPeers();
30
+ return peers.find((p) => p.id === id) ?? null;
31
+ }
32
+ function addPeer(peer) {
33
+ const peers = loadPeers();
34
+ const idx = peers.findIndex((p) => p.id === peer.id);
35
+ if (idx >= 0) {
36
+ peers[idx] = peer;
37
+ } else {
38
+ peers.push(peer);
39
+ }
40
+ savePeers(peers);
41
+ }
42
+ function revokePeer(id) {
43
+ const peers = loadPeers();
44
+ const peer = peers.find((p) => p.id === id);
45
+ if (!peer) return false;
46
+ peer.revoked = true;
47
+ savePeers(peers);
48
+ return true;
49
+ }
50
+ function forgetAllPeers() {
51
+ const peers = loadPeers();
52
+ const count = peers.length;
53
+ if (fs.existsSync(PEERS_FILE)) {
54
+ fs.unlinkSync(PEERS_FILE);
55
+ }
56
+ return count;
57
+ }
58
+ function updatePeerLastSeen(id) {
59
+ const peers = loadPeers();
60
+ const peer = peers.find((p) => p.id === id);
61
+ if (!peer) return;
62
+ peer.lastSeen = (/* @__PURE__ */ new Date()).toISOString();
63
+ savePeers(peers);
64
+ }
65
+ function updatePeerAgents(id, agents) {
66
+ const peers = loadPeers();
67
+ const peer = peers.find((p) => p.id === id);
68
+ if (!peer) return;
69
+ peer.agents = agents;
70
+ savePeers(peers);
71
+ }
72
+ function generatePairing() {
73
+ const sharedSecret = crypto.randomBytes(32).toString("hex");
74
+ const code = (parseInt(crypto.randomBytes(3).toString("hex"), 16) % 1e6).toString().padStart(6, "0");
75
+ const codeHash = crypto.createHash("sha256").update(code).digest("hex");
76
+ return {
77
+ code,
78
+ codeHash,
79
+ sharedSecret,
80
+ createdAt: Date.now()
81
+ };
82
+ }
83
+ function verifyPairingCode(state, code) {
84
+ if (Date.now() - state.createdAt > PAIRING_TTL_MS) {
85
+ return false;
86
+ }
87
+ const hash = crypto.createHash("sha256").update(code).digest("hex");
88
+ return hash === state.codeHash;
89
+ }
90
+ function computeHmacProof(challenge, codeHash) {
91
+ return crypto.createHmac("sha256", codeHash).update(challenge).digest("hex");
92
+ }
93
+ function verifyHmacProof(challenge, codeHash, proof) {
94
+ const expected = computeHmacProof(challenge, codeHash);
95
+ if (expected.length !== proof.length) return false;
96
+ try {
97
+ return crypto.timingSafeEqual(
98
+ Buffer.from(expected, "hex"),
99
+ Buffer.from(proof, "hex")
100
+ );
101
+ } catch {
102
+ return false;
103
+ }
104
+ }
105
+
106
+ export {
107
+ PEERS_FILE,
108
+ PAIRING_TTL_MS,
109
+ loadPeers,
110
+ savePeers,
111
+ findPeer,
112
+ addPeer,
113
+ revokePeer,
114
+ forgetAllPeers,
115
+ updatePeerLastSeen,
116
+ updatePeerAgents,
117
+ generatePairing,
118
+ verifyPairingCode,
119
+ computeHmacProof,
120
+ verifyHmacProof
121
+ };
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  getProvider,
7
7
  initializeProviders
8
- } from "./chunk-FS3WTUHY.js";
8
+ } from "./chunk-TXESEO7Y.js";
9
9
  import {
10
10
  loadAgentsManifest
11
11
  } from "./chunk-PMXRGPRQ.js";
@@ -614,6 +614,7 @@ var AgentSpawner = class {
614
614
  agent: agentName,
615
615
  task,
616
616
  status: "success",
617
+ completionVerified: false,
617
618
  outputs: {
618
619
  artifacts: [],
619
620
  symbols: context.symbols,
@@ -681,6 +682,29 @@ var AgentSpawner = class {
681
682
  if (this.budgetTracker) {
682
683
  this.budgetTracker.recordUsage(agentName, relay.metrics.tokens_used, model);
683
684
  }
685
+ if (relay.status === "success") {
686
+ const hasArtifacts = relay.outputs.artifacts.length > 0;
687
+ const hasDecisions = relay.outputs.decisions.length > 0;
688
+ const hasHandoff = !!relay.handoff;
689
+ const didFileWork = relay.metrics.files_written > 0;
690
+ const isArchitect = agentName === "architect";
691
+ const isBuilder = agentName === "builder";
692
+ if (isBuilder && !didFileWork && !hasHandoff) {
693
+ relay.status = "partial";
694
+ } else if (!hasArtifacts && !hasDecisions && !hasHandoff && !didFileWork) {
695
+ relay.status = "partial";
696
+ }
697
+ relay.completionVerified = true;
698
+ if (relay.status === "partial" && !isArchitect) {
699
+ if (options.onMessage) {
700
+ options.onMessage({
701
+ type: "text",
702
+ content: `[completion-check] Agent "${agentName}" downgraded from success \u2192 partial: no meaningful output detected.`,
703
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
704
+ });
705
+ }
706
+ }
707
+ }
684
708
  if (this.auditLogger) {
685
709
  const agentLog = {
686
710
  name: agentName,