@rubytech/create-sitedesk-code 0.1.513 → 0.1.515

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 (199) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/docs/superpowers/plans/2026-07-27-task-2016-disabled-agent-routing.md +624 -0
  3. package/payload/platform/docs/superpowers/plans/2026-07-27-task-2052-account-machinery-write-fence.md +250 -0
  4. package/payload/platform/docs/superpowers/specs/2026-07-27-task-2016-disabled-agent-routing-design.md +139 -0
  5. package/payload/platform/docs/superpowers/specs/2026-07-27-task-2028-declared-file-write-deny-design.md +2 -1
  6. package/payload/platform/docs/superpowers/specs/2026-07-27-task-2052-account-machinery-write-fence-design.md +150 -0
  7. package/payload/platform/plugins/admin/hooks/__tests__/fs-schema-guard.test.sh +41 -0
  8. package/payload/platform/plugins/admin/hooks/fs-schema-guard-bash-post.sh +8 -0
  9. package/payload/platform/plugins/admin/hooks/fs-schema-guard.sh +40 -1
  10. package/payload/platform/plugins/admin/mcp/dist/index.js +14 -16
  11. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  12. package/payload/platform/plugins/admin/mcp/dist/specialist-registry.d.ts +14 -0
  13. package/payload/platform/plugins/admin/mcp/dist/specialist-registry.d.ts.map +1 -0
  14. package/payload/platform/plugins/admin/mcp/dist/specialist-registry.js +57 -0
  15. package/payload/platform/plugins/admin/mcp/dist/specialist-registry.js.map +1 -0
  16. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +15 -3
  17. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +12 -0
  18. package/payload/platform/plugins/cloudflare/bin/schema-exposed-dirs.mjs +1 -1
  19. package/payload/platform/plugins/docs/references/admin-ui.md +14 -2
  20. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +3 -3
  21. package/payload/platform/scripts/__tests__/agents-md-bootstrap.test.sh +47 -0
  22. package/payload/platform/scripts/lib/agents-md-bootstrap.sh +58 -1
  23. package/payload/platform/services/claude-session-manager/dist/config.d.ts +48 -12
  24. package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
  25. package/payload/platform/services/claude-session-manager/dist/config.js +65 -15
  26. package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
  27. package/payload/platform/services/claude-session-manager/dist/index.js +7 -4
  28. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  29. package/payload/platform/services/claude-session-manager/dist/rootless-client-audit.d.ts.map +1 -1
  30. package/payload/platform/services/claude-session-manager/dist/rootless-client-audit.js +17 -2
  31. package/payload/platform/services/claude-session-manager/dist/rootless-client-audit.js.map +1 -1
  32. package/payload/platform/templates/account-schema/SCHEMA.md +17 -0
  33. package/payload/server/public/activity.html +5 -5
  34. package/payload/server/public/agents.html +4 -4
  35. package/payload/server/public/assets/{AdminLoginScreens-bksN0XPe.js → AdminLoginScreens-Cs1jSnOF.js} +1 -1
  36. package/payload/server/public/assets/AdminLoginScreens-Cs1jSnOF.js.br +0 -0
  37. package/payload/server/public/assets/AdminLoginScreens-Cs1jSnOF.js.gz +0 -0
  38. package/payload/server/public/assets/{AdminShell-BMPEWNZk.js → AdminShell-DkrURZnF.js} +1 -1
  39. package/payload/server/public/assets/AdminShell-DkrURZnF.js.br +0 -0
  40. package/payload/server/public/assets/AdminShell-DkrURZnF.js.gz +0 -0
  41. package/payload/server/public/assets/{activity-ByWYF5dC.js → activity-BgZISMuE.js} +1 -1
  42. package/payload/server/public/assets/activity-BgZISMuE.js.br +0 -0
  43. package/payload/server/public/assets/activity-BgZISMuE.js.gz +0 -0
  44. package/payload/server/public/assets/{admin-6QN-k3zQ.js → admin-DjFysc3-.js} +1 -1
  45. package/payload/server/public/assets/admin-DjFysc3-.js.br +0 -0
  46. package/payload/server/public/assets/admin-DjFysc3-.js.gz +0 -0
  47. package/payload/server/public/assets/{agents-C0rTfrYd.js → agents-Bx-MSZW6.js} +1 -1
  48. package/payload/server/public/assets/agents-Bx-MSZW6.js.br +0 -0
  49. package/payload/server/public/assets/agents-Bx-MSZW6.js.gz +0 -0
  50. package/payload/server/public/assets/{browser-4tTaem8N.js → browser-1I7syhHu.js} +1 -1
  51. package/payload/server/public/assets/browser-1I7syhHu.js.br +0 -0
  52. package/payload/server/public/assets/browser-1I7syhHu.js.gz +0 -0
  53. package/payload/server/public/assets/{calendar-BEjnkKG1.js → calendar-D_04JIo1.js} +1 -1
  54. package/payload/server/public/assets/calendar-D_04JIo1.js.br +0 -0
  55. package/payload/server/public/assets/calendar-D_04JIo1.js.gz +0 -0
  56. package/payload/server/public/assets/chat-BFH3FM5a.js +1 -0
  57. package/payload/server/public/assets/chat-BFH3FM5a.js.br +0 -0
  58. package/payload/server/public/assets/chat-BFH3FM5a.js.gz +0 -0
  59. package/payload/server/public/assets/chevron-left-Ux9-qLkk.js +1 -0
  60. package/payload/server/public/assets/chevron-right-BwIuCfyG.js +1 -0
  61. package/payload/server/public/assets/chevron-right-BwIuCfyG.js.br +0 -0
  62. package/payload/server/public/assets/clock-DhJdZRhC.js +1 -0
  63. package/payload/server/public/assets/clock-DhJdZRhC.js.br +0 -0
  64. package/payload/server/public/assets/data-ChY_uSIk.js +1 -0
  65. package/payload/server/public/assets/data-ChY_uSIk.js.br +0 -0
  66. package/payload/server/public/assets/data-ChY_uSIk.js.gz +0 -0
  67. package/payload/server/public/assets/{file-text-DMKw3nIk.js → file-text-DkvKqHMx.js} +1 -1
  68. package/payload/server/public/assets/file-text-DkvKqHMx.js.br +0 -0
  69. package/payload/server/public/assets/file-text-DkvKqHMx.js.gz +0 -0
  70. package/payload/server/public/assets/{graph-C3vW8lvw.js → graph-CCZhrwZX.js} +1 -1
  71. package/payload/server/public/assets/graph-CCZhrwZX.js.br +0 -0
  72. package/payload/server/public/assets/graph-CCZhrwZX.js.gz +0 -0
  73. package/payload/server/public/assets/{graph-labels-BZgd0L6n.js → graph-labels-BJ7puQkX.js} +1 -1
  74. package/payload/server/public/assets/graph-labels-BJ7puQkX.js.br +0 -0
  75. package/payload/server/public/assets/graph-labels-BJ7puQkX.js.gz +0 -0
  76. package/payload/server/public/assets/{maximize-2-la3IBA3M.js → maximize-2-Xdj804U1.js} +1 -1
  77. package/payload/server/public/assets/maximize-2-Xdj804U1.js.br +0 -0
  78. package/payload/server/public/assets/maximize-2-Xdj804U1.js.gz +0 -0
  79. package/payload/server/public/assets/{operator-D9NgVL9_.js → operator-BkfNpBs7.js} +1 -1
  80. package/payload/server/public/assets/operator-BkfNpBs7.js.br +0 -0
  81. package/payload/server/public/assets/operator-BkfNpBs7.js.gz +0 -0
  82. package/payload/server/public/assets/{page-DC11gesX.js → page-BoYc9c4a.js} +1 -1
  83. package/payload/server/public/assets/page-BoYc9c4a.js.br +0 -0
  84. package/payload/server/public/assets/page-BoYc9c4a.js.gz +0 -0
  85. package/payload/server/public/assets/{page-BWFHRIAH.js → page-D5n8ShE7.js} +1 -1
  86. package/payload/server/public/assets/page-D5n8ShE7.js.br +0 -0
  87. package/payload/server/public/assets/page-D5n8ShE7.js.gz +0 -0
  88. package/payload/server/public/assets/{public-DQbbLHQN.js → public-CX5XSrxD.js} +1 -1
  89. package/payload/server/public/assets/public-CX5XSrxD.js.br +0 -0
  90. package/payload/server/public/assets/public-CX5XSrxD.js.gz +0 -0
  91. package/payload/server/public/assets/{rotate-ccw-OQD5si8N.js → rotate-ccw-dh_OhL23.js} +1 -1
  92. package/payload/server/public/assets/rotate-ccw-dh_OhL23.js.br +0 -0
  93. package/payload/server/public/assets/rotate-ccw-dh_OhL23.js.gz +0 -0
  94. package/payload/server/public/assets/{routines-asrBGZUR.js → routines-bb7dxcrr.js} +1 -1
  95. package/payload/server/public/assets/routines-bb7dxcrr.js.br +0 -0
  96. package/payload/server/public/assets/routines-bb7dxcrr.js.gz +0 -0
  97. package/payload/server/public/assets/{skills-D4ECwoxa.js → skills-TeMwxXmJ.js} +1 -1
  98. package/payload/server/public/assets/skills-TeMwxXmJ.js.br +0 -0
  99. package/payload/server/public/assets/skills-TeMwxXmJ.js.gz +0 -0
  100. package/payload/server/public/assets/{tasks-U3QdbUsO.js → tasks-BqBBJlkg.js} +1 -1
  101. package/payload/server/public/assets/tasks-BqBBJlkg.js.br +0 -0
  102. package/payload/server/public/assets/tasks-BqBBJlkg.js.gz +0 -0
  103. package/payload/server/public/assets/{time-entry-format-BgdTKgYr.js → time-entry-format-Cy_T-wiD.js} +1 -1
  104. package/payload/server/public/assets/time-entry-format-Cy_T-wiD.js.br +3 -0
  105. package/payload/server/public/assets/time-entry-format-Cy_T-wiD.js.gz +0 -0
  106. package/payload/server/public/assets/{triangle-alert-Ck_3VhT9.js → triangle-alert-D-bSbPnX.js} +1 -1
  107. package/payload/server/public/assets/triangle-alert-D-bSbPnX.js.br +1 -0
  108. package/payload/server/public/assets/triangle-alert-D-bSbPnX.js.gz +0 -0
  109. package/payload/server/public/assets/{useCopyFeedback-BdUwyNpa.js → useCopyFeedback-L7L55nFl.js} +1 -1
  110. package/payload/server/public/assets/useCopyFeedback-L7L55nFl.js.br +0 -0
  111. package/payload/server/public/assets/useCopyFeedback-L7L55nFl.js.gz +0 -0
  112. package/payload/server/public/assets/useSubAccountSwitcher-BYl2c7xA.css +1 -0
  113. package/payload/server/public/assets/useSubAccountSwitcher-BYl2c7xA.css.br +0 -0
  114. package/payload/server/public/assets/useSubAccountSwitcher-BYl2c7xA.css.gz +0 -0
  115. package/payload/server/public/assets/{useVoiceRecorder-ChnBrzbZ.js → useVoiceRecorder-MuZ7lpet.js} +1 -1
  116. package/payload/server/public/assets/useVoiceRecorder-MuZ7lpet.js.br +0 -0
  117. package/payload/server/public/assets/useVoiceRecorder-MuZ7lpet.js.gz +0 -0
  118. package/payload/server/public/assets/{wrench-Cpee3C3J.js → wrench-DUG1SZQB.js} +1 -1
  119. package/payload/server/public/assets/wrench-DUG1SZQB.js.br +0 -0
  120. package/payload/server/public/assets/wrench-DUG1SZQB.js.gz +0 -0
  121. package/payload/server/public/brand-defaults.css +2 -0
  122. package/payload/server/public/browser.html +4 -4
  123. package/payload/server/public/calendar.html +7 -7
  124. package/payload/server/public/chat.html +13 -13
  125. package/payload/server/public/data.html +11 -11
  126. package/payload/server/public/graph.html +9 -9
  127. package/payload/server/public/index.html +14 -14
  128. package/payload/server/public/operator.html +14 -14
  129. package/payload/server/public/public.html +13 -13
  130. package/payload/server/public/routines.html +6 -6
  131. package/payload/server/public/skills.html +5 -5
  132. package/payload/server/public/tasks.html +6 -6
  133. package/payload/server/server.js +138 -19
  134. package/payload/server/public/assets/AdminLoginScreens-bksN0XPe.js.br +0 -0
  135. package/payload/server/public/assets/AdminLoginScreens-bksN0XPe.js.gz +0 -0
  136. package/payload/server/public/assets/AdminShell-BMPEWNZk.js.br +0 -0
  137. package/payload/server/public/assets/AdminShell-BMPEWNZk.js.gz +0 -0
  138. package/payload/server/public/assets/activity-ByWYF5dC.js.br +0 -0
  139. package/payload/server/public/assets/activity-ByWYF5dC.js.gz +0 -0
  140. package/payload/server/public/assets/admin-6QN-k3zQ.js.br +0 -0
  141. package/payload/server/public/assets/admin-6QN-k3zQ.js.gz +0 -0
  142. package/payload/server/public/assets/agents-C0rTfrYd.js.br +0 -0
  143. package/payload/server/public/assets/agents-C0rTfrYd.js.gz +0 -0
  144. package/payload/server/public/assets/browser-4tTaem8N.js.br +0 -0
  145. package/payload/server/public/assets/browser-4tTaem8N.js.gz +0 -0
  146. package/payload/server/public/assets/calendar-BEjnkKG1.js.br +0 -0
  147. package/payload/server/public/assets/calendar-BEjnkKG1.js.gz +0 -0
  148. package/payload/server/public/assets/chat-DBgzjDIE.js +0 -1
  149. package/payload/server/public/assets/chat-DBgzjDIE.js.br +0 -0
  150. package/payload/server/public/assets/chat-DBgzjDIE.js.gz +0 -0
  151. package/payload/server/public/assets/chevron-left-DqYv3oFh.js +0 -1
  152. package/payload/server/public/assets/chevron-right-CQfPGsFb.js +0 -1
  153. package/payload/server/public/assets/chevron-right-CQfPGsFb.js.br +0 -0
  154. package/payload/server/public/assets/clock-Dn6FHB51.js +0 -1
  155. package/payload/server/public/assets/clock-Dn6FHB51.js.br +0 -0
  156. package/payload/server/public/assets/clock-Dn6FHB51.js.gz +0 -0
  157. package/payload/server/public/assets/data-D_e6Vdfd.js +0 -1
  158. package/payload/server/public/assets/data-D_e6Vdfd.js.br +0 -0
  159. package/payload/server/public/assets/data-D_e6Vdfd.js.gz +0 -0
  160. package/payload/server/public/assets/file-text-DMKw3nIk.js.br +0 -0
  161. package/payload/server/public/assets/file-text-DMKw3nIk.js.gz +0 -0
  162. package/payload/server/public/assets/graph-C3vW8lvw.js.br +0 -0
  163. package/payload/server/public/assets/graph-C3vW8lvw.js.gz +0 -0
  164. package/payload/server/public/assets/graph-labels-BZgd0L6n.js.br +0 -0
  165. package/payload/server/public/assets/graph-labels-BZgd0L6n.js.gz +0 -0
  166. package/payload/server/public/assets/maximize-2-la3IBA3M.js.br +0 -0
  167. package/payload/server/public/assets/maximize-2-la3IBA3M.js.gz +0 -0
  168. package/payload/server/public/assets/operator-D9NgVL9_.js.br +0 -0
  169. package/payload/server/public/assets/operator-D9NgVL9_.js.gz +0 -0
  170. package/payload/server/public/assets/page-BWFHRIAH.js.br +0 -0
  171. package/payload/server/public/assets/page-BWFHRIAH.js.gz +0 -0
  172. package/payload/server/public/assets/page-DC11gesX.js.br +0 -0
  173. package/payload/server/public/assets/page-DC11gesX.js.gz +0 -0
  174. package/payload/server/public/assets/public-DQbbLHQN.js.br +0 -0
  175. package/payload/server/public/assets/public-DQbbLHQN.js.gz +0 -0
  176. package/payload/server/public/assets/rotate-ccw-OQD5si8N.js.br +0 -0
  177. package/payload/server/public/assets/rotate-ccw-OQD5si8N.js.gz +0 -0
  178. package/payload/server/public/assets/routines-asrBGZUR.js.br +0 -0
  179. package/payload/server/public/assets/routines-asrBGZUR.js.gz +0 -0
  180. package/payload/server/public/assets/skills-D4ECwoxa.js.br +0 -0
  181. package/payload/server/public/assets/skills-D4ECwoxa.js.gz +0 -0
  182. package/payload/server/public/assets/tasks-U3QdbUsO.js.br +0 -0
  183. package/payload/server/public/assets/tasks-U3QdbUsO.js.gz +0 -0
  184. package/payload/server/public/assets/time-entry-format-BgdTKgYr.js.br +0 -0
  185. package/payload/server/public/assets/time-entry-format-BgdTKgYr.js.gz +0 -0
  186. package/payload/server/public/assets/triangle-alert-Ck_3VhT9.js.br +0 -0
  187. package/payload/server/public/assets/triangle-alert-Ck_3VhT9.js.gz +0 -0
  188. package/payload/server/public/assets/useCopyFeedback-BdUwyNpa.js.br +0 -0
  189. package/payload/server/public/assets/useCopyFeedback-BdUwyNpa.js.gz +0 -0
  190. package/payload/server/public/assets/useSubAccountSwitcher-DOWQXDT8.css +0 -1
  191. package/payload/server/public/assets/useSubAccountSwitcher-DOWQXDT8.css.br +0 -0
  192. package/payload/server/public/assets/useSubAccountSwitcher-DOWQXDT8.css.gz +0 -0
  193. package/payload/server/public/assets/useVoiceRecorder-ChnBrzbZ.js.br +0 -0
  194. package/payload/server/public/assets/useVoiceRecorder-ChnBrzbZ.js.gz +0 -0
  195. package/payload/server/public/assets/wrench-Cpee3C3J.js.br +0 -2
  196. package/payload/server/public/assets/wrench-Cpee3C3J.js.gz +0 -0
  197. /package/payload/server/public/assets/{useSubAccountSwitcher-CJKjEPNN.js → useSubAccountSwitcher-DH0P6QMV.js} +0 -0
  198. /package/payload/server/public/assets/{useSubAccountSwitcher-CJKjEPNN.js.br → useSubAccountSwitcher-DH0P6QMV.js.br} +0 -0
  199. /package/payload/server/public/assets/{useSubAccountSwitcher-CJKjEPNN.js.gz → useSubAccountSwitcher-DH0P6QMV.js.gz} +0 -0
@@ -5,6 +5,12 @@
5
5
  # - the target's first path segment must be in the allowed top-level set
6
6
  # (parsed from the fenced ```allowed-top-level block of the account's
7
7
  # SCHEMA.md — our own structured data, not CLI prose);
8
+ # - a target whose first path segment is named in the fenced
9
+ # ```agent-denied-top-level block is blocked even though that name is in the
10
+ # allowed set: those entries are the account's control plane (identity,
11
+ # schema, credentials, agent settings, git dir), and none of them is ever
12
+ # authored by an agent file edit. The block message quotes the reason the
13
+ # fence carries for that name;
8
14
  # - a target whose first path segment is a plugin-declared file (parsed from
9
15
  # the fenced ```declared-files block of the same SCHEMA.md) is blocked even
10
16
  # though that name is in the allowed set: the allowed set is a layout list,
@@ -18,7 +24,7 @@
18
24
  #
19
25
  # Exit codes: 0 = allow, 2 = block (stderr shown to the agent). Fail closed when
20
26
  # the tool call cannot be inspected (tty or empty stdin). Every block logs
21
- # [fs-guard] blocked path=<rel> reason=<top-level|declared-file|over-deep|bad-name>
27
+ # [fs-guard] blocked path=<rel> reason=<top-level|account-machinery|declared-file|over-deep|bad-name>
22
28
  # No task numbers / internal refs in any operator-visible string.
23
29
 
24
30
  set -uo pipefail
@@ -88,6 +94,39 @@ if ! printf '%s\n' "$ALLOWED" | grep -qxF "$SEG0"; then
88
94
  exit 2
89
95
  fi
90
96
 
97
+ # Account-machinery check. Some entries in the allowed set are the account's own
98
+ # control plane rather than operator data: the identity file, the schema this
99
+ # hook parses, the credential store, the agent's own settings and hooks, and the
100
+ # git dir. The allowed set says which names may EXIST at the account root, not
101
+ # which an agent may author, so each of these is named in a second fence together
102
+ # with the reason it is off-limits. None of the five is authored through
103
+ # Write/Edit/NotebookEdit: platform bash and Node write four of them, and git
104
+ # itself writes .git, so denying them costs no legitimate writer. This denies
105
+ # the agent's FILE-EDIT tools only, which is the whole surface the hook governs
106
+ # — a Bash command still reaches these paths, and one sanctioned path relies on
107
+ # that (the data-portal skill appends its fetch secret to secrets/ with a shell
108
+ # redirect). The set and its reasons come from the account's own SCHEMA.md, so
109
+ # the hook hard-codes no list. There is no owning plugin to name here, which is
110
+ # why this fence carries a reason column the declared-files fence does not need.
111
+ #
112
+ # Not to be confused with the same phrase in account-dir-schema-reconcile.ts,
113
+ # whose "account's own machinery" is the never-a-stray set and covers a
114
+ # different membership (.quarantine and AGENTS.md are in it; secrets/ is not).
115
+ #
116
+ # No fence means nothing to deny, the same fail-open posture as the
117
+ # missing-schema case above. Which accounts lack it is not uniform: setup-account.sh
118
+ # re-provisions only the house account, and provision copies the template whole,
119
+ # so the house account gains the fence on the next install while a client
120
+ # sub-account — provisioned once, at creation — keeps a fence-less schema until a
121
+ # durable backfill lands.
122
+ DENIED=$(awk '/^```agent-denied-top-level$/{f=1;next} /^```$/{f=0} f' "$ACCOUNT_DIR/SCHEMA.md")
123
+ if [ -n "$DENIED" ] && printf '%s\n' "$DENIED" | awk -F'\t' -v n="$SEG0" '$1==n{found=1} END{exit !found}'; then
124
+ WHY=$(printf '%s\n' "$DENIED" | awk -F'\t' -v n="$SEG0" '$1==n{print $2; exit}')
125
+ echo "[fs-guard] blocked path=$REL reason=account-machinery" >&2
126
+ echo "Blocked: '$SEG0' is this account's own machinery, not operator data: $WHY. Change it through the code that owns it." >&2
127
+ exit 2
128
+ fi
129
+
91
130
  # Declared-file check. A file declared in the fence is written whole by platform
92
131
  # code, so an agent write to it is blocked even though the name is in the allowed
93
132
  # set: that set says which names may exist at the account root, not which an
@@ -21,6 +21,7 @@ import QRCode from "qrcode";
21
21
  import { getSession, closeDriver } from "./lib/neo4j.js";
22
22
  import { findSkillOwners, searchSkills, computePluginReadHint, loadSkill, parseRequiredInputs, adminAuthoringSkillBlock, skillSlugFromReadArgs, AUTHORING_DISPATCH_HINT } from "./skill-resolution.js";
23
23
  import { storeSkillToAccount } from "./store-skill-core.js";
24
+ import { classifySpecialists } from "./specialist-registry.js";
24
25
  import { resolvePublicHostname } from "./lib/public-hostname.js";
25
26
  import { resolveAdminHostname } from "./lib/admin-hostname.js";
26
27
  import { publishSite } from "./tools/publish-site.js";
@@ -434,25 +435,22 @@ eagerTool(server, "system-status", "Check health of all SiteDesk platform servic
434
435
  }
435
436
  else {
436
437
  const content = readFileSync(agentsMdPath, "utf-8");
437
- const entries = content.match(/^- \*\*specialists:([^*]+)\*\*/gm);
438
- if (!entries || entries.length === 0) {
438
+ // Task 2016 — `missing` and `disabled` are different answers. An agent
439
+ // the operator switched off has no file here by design, and reporting
440
+ // that as a fault trains the operator to ignore the real ones.
441
+ const report = classifySpecialists({
442
+ agentsMd: content,
443
+ specialistsAgentsDir,
444
+ accountDir,
445
+ chromeUp,
446
+ });
447
+ if (report.registered === 0) {
439
448
  checks.specialists = "not configured (AGENTS.md empty)";
440
449
  }
441
450
  else {
442
- const lines = [];
443
- for (const entry of entries) {
444
- const nameMatch = entry.match(/specialists:([^*]+)/);
445
- if (!nameMatch)
446
- continue;
447
- const name = nameMatch[1];
448
- const fileExists = existsSync(join(specialistsAgentsDir, `${name}.md`));
449
- let status = fileExists ? "ok" : "missing file";
450
- if (name === "personal-assistant" && !chromeUp) {
451
- status = "degraded — chrome not running";
452
- }
453
- lines.push(` ${name}: ${status}`);
454
- }
455
- checks.specialists = `${entries.length} registered\n${lines.join("\n")}`;
451
+ checks.specialists =
452
+ `${report.registered} registered, missing=${report.missing} disabled=${report.disabled}\n` +
453
+ report.lines.join("\n");
456
454
  }
457
455
  }
458
456
  }