chainlesschain 0.162.9 → 0.162.12

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 (144) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-BgQaSGlp.js → AIOps-C3TDNq29.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-BhTVuWPn.js → ActionButton-C9fE18pE.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-BO1jPw9V.js → Analytics-wnZF602C.js} +1 -1
  5. package/src/assets/web-panel/assets/{AppLayout-VX_9bmhs.js → AppLayout-BjgTMK7O.js} +2 -2
  6. package/src/assets/web-panel/assets/{Audit-Qvf0oq_Y.js → Audit-BBL0BW5_.js} +1 -1
  7. package/src/assets/web-panel/assets/{Backup-TjzfYOeC.js → Backup-BKLqYCWU.js} +1 -1
  8. package/src/assets/web-panel/assets/{BaseInput-BLuumXTZ.js → BaseInput-BGSzMCZs.js} +1 -1
  9. package/src/assets/web-panel/assets/{Chat-CXrCvi7a.js → Chat-CQWzZWEY.js} +1 -1
  10. package/src/assets/web-panel/assets/{Checkbox--DOdo_Nz.js → Checkbox-BkTri12Q.js} +1 -1
  11. package/src/assets/web-panel/assets/{Codegen-DAJaraZ7.js → Codegen-BH1m09EO.js} +1 -1
  12. package/src/assets/web-panel/assets/{Col-CezPMM8r.js → Col-BXnBuqIa.js} +1 -1
  13. package/src/assets/web-panel/assets/{Community-95cmfh28.js → Community-C_Nr4XCx.js} +1 -1
  14. package/src/assets/web-panel/assets/{Compact-GlEOCt_z.js → Compact-Du6GwLrj.js} +1 -1
  15. package/src/assets/web-panel/assets/{Compliance-Np9rHlBD.js → Compliance-66M0oi1Q.js} +1 -1
  16. package/src/assets/web-panel/assets/{Cowork-DhobloKt.js → Cowork-DQrkZRNd.js} +1 -1
  17. package/src/assets/web-panel/assets/{Cron-DsvEYSze.js → Cron-CwdIFH_v.js} +1 -1
  18. package/src/assets/web-panel/assets/{Crosschain-D5h0edtx.js → Crosschain-DqlcrQ9L.js} +1 -1
  19. package/src/assets/web-panel/assets/{DID-BgEIvDQh.js → DID-OmPLKf7L.js} +1 -1
  20. package/src/assets/web-panel/assets/{Dashboard-BQ9z2Vs6.js → Dashboard-D_dampTL.js} +2 -2
  21. package/src/assets/web-panel/assets/{Dropdown-zDSAIpGs.js → Dropdown-CA1W7jAn.js} +1 -1
  22. package/src/assets/web-panel/assets/{Federation-Bhn4LZO4.js → Federation-Chlk9a7s.js} +1 -1
  23. package/src/assets/web-panel/assets/{FormItemContext-D_NMXINy.js → FormItemContext-t0UqYFLq.js} +1 -1
  24. package/src/assets/web-panel/assets/{Git-D6iEbQtW.js → Git-CEq0raYm.js} +1 -1
  25. package/src/assets/web-panel/assets/{Governance-DXZrVh5v.js → Governance-C06CX7Ge.js} +1 -1
  26. package/src/assets/web-panel/assets/{Inference-DxgJQVdT.js → Inference-6VIFHxIP.js} +1 -1
  27. package/src/assets/web-panel/assets/{KnowledgeGraph-B6iB6jMD.js → KnowledgeGraph-BCJPjMBQ.js} +1 -1
  28. package/src/assets/web-panel/assets/{Logs-Bam2v_rb.js → Logs-BBpOYFct.js} +1 -1
  29. package/src/assets/web-panel/assets/{Marketplace-hmoE5rhf.js → Marketplace-BFH6jMWt.js} +1 -1
  30. package/src/assets/web-panel/assets/{McpTools-XLZTBQ9E.js → McpTools-uCFvRqGs.js} +1 -1
  31. package/src/assets/web-panel/assets/{Memory-C-NXlOEE.js → Memory-B0Kux_KT.js} +1 -1
  32. package/src/assets/web-panel/assets/{MobileBridge-Xi_Xzm7u.js → MobileBridge-DHow2jiK.js} +1 -1
  33. package/src/assets/web-panel/assets/{MobileProjects-BVxyrtNp.js → MobileProjects-BFo9YQZp.js} +1 -1
  34. package/src/assets/web-panel/assets/{Mtc-DY8puwdE.js → Mtc-riOh1G_F.js} +1 -1
  35. package/src/assets/web-panel/assets/{MtcAudit-DJShrgkU.js → MtcAudit-Bm-hE2SP.js} +1 -1
  36. package/src/assets/web-panel/assets/{Multisig-CsNe5Aor.js → Multisig-DfUQxh5a.js} +1 -1
  37. package/src/assets/web-panel/assets/{NLProgramming-Me0yNI2U.js → NLProgramming-DuNvLBEq.js} +1 -1
  38. package/src/assets/web-panel/assets/{Notes-D_g-p2Tg.js → Notes-DB20wd3c.js} +1 -1
  39. package/src/assets/web-panel/assets/{NotificationSettings-DT7K69Vl.js → NotificationSettings-CB-GkOWR.js} +1 -1
  40. package/src/assets/web-panel/assets/{Organization-D4hlrApo.js → Organization-3bU7PZuG.js} +1 -1
  41. package/src/assets/web-panel/assets/{Overflow-BAvaHETK.js → Overflow-BGCPP_0Y.js} +1 -1
  42. package/src/assets/web-panel/assets/{P2P-D570BCdt.js → P2P-BHgAe1oC.js} +1 -1
  43. package/src/assets/web-panel/assets/{Permissions-5lYj-mLS.js → Permissions-BuOD4xwc.js} +1 -1
  44. package/src/assets/web-panel/assets/{PersonalDataHub-DwFzyawJ.js → PersonalDataHub--WA-aZAJ.js} +1 -1
  45. package/src/assets/web-panel/assets/{Pipeline-Ce72g3py.js → Pipeline-DBS5U4LB.js} +1 -1
  46. package/src/assets/web-panel/assets/{Privacy-BsLyD5gE.js → Privacy-UNjIc5El.js} +1 -1
  47. package/src/assets/web-panel/assets/{ProjectInit-CE0ATemT.js → ProjectInit-CicqCJGy.js} +1 -1
  48. package/src/assets/web-panel/assets/{ProjectSettings-Cnevuf69.js → ProjectSettings-CIxAbt4Y.js} +1 -1
  49. package/src/assets/web-panel/assets/{Projects-Bwe8FTDK.js → Projects-BJycZScO.js} +1 -1
  50. package/src/assets/web-panel/assets/{Providers-BlN2_n0e.js → Providers-DxXvprme.js} +1 -1
  51. package/src/assets/web-panel/assets/{QuickAsk-D90_0612.js → QuickAsk-rrqjU8_Y.js} +1 -1
  52. package/src/assets/web-panel/assets/{Recommend-CAdqobLh.js → Recommend-BEwHMhI7.js} +1 -1
  53. package/src/assets/web-panel/assets/{Reputation-gAeuZfsd.js → Reputation-DoVKCCMn.js} +1 -1
  54. package/src/assets/web-panel/assets/{Row-Dsz4KRaU.js → Row-F5XcDhHr.js} +1 -1
  55. package/src/assets/web-panel/assets/{RssFeed-BuTu0HKl.js → RssFeed-cZrRG7k8.js} +1 -1
  56. package/src/assets/web-panel/assets/{Search-B6jcG3iF.js → Search-B9ctZjqx.js} +1 -1
  57. package/src/assets/web-panel/assets/{Security-CcEX8TPI.js → Security-Z62hl1mc.js} +1 -1
  58. package/src/assets/web-panel/assets/{Services-BBbLFK_e.js → Services-CQf5XqgZ.js} +1 -1
  59. package/src/assets/web-panel/assets/{Skeleton-CARhezYN.js → Skeleton-DuCKw2Eh.js} +1 -1
  60. package/src/assets/web-panel/assets/{Skills-B9dCFkON.js → Skills-qVkhva0s.js} +1 -1
  61. package/src/assets/web-panel/assets/{Sla-Ds2N-wGY.js → Sla-BQbatr7s.js} +1 -1
  62. package/src/assets/web-panel/assets/{SpeechSettings-flimA105.js → SpeechSettings-DLFBzAgD.js} +1 -1
  63. package/src/assets/web-panel/assets/{SyncSettings-B1tJs8pr.js → SyncSettings-CrzETZMW.js} +1 -1
  64. package/src/assets/web-panel/assets/{Tasks-Cs7_NAOr.js → Tasks-D_EQ1nJ7.js} +1 -1
  65. package/src/assets/web-panel/assets/{Templates-D3iXQ2gE.js → Templates-D4y-dGRc.js} +1 -1
  66. package/src/assets/web-panel/assets/{Tenant-Z6mUmAVT.js → Tenant-2XI0jkPn.js} +1 -1
  67. package/src/assets/web-panel/assets/{Terminal-PIR1l-39.js → Terminal-fUi5V2Z9.js} +1 -1
  68. package/src/assets/web-panel/assets/{Tokens-BLjbrTa1.js → Tokens-BuUNB2mg.js} +1 -1
  69. package/src/assets/web-panel/assets/{Trigger-CIJzC6pS.js → Trigger-7DqLLuej.js} +1 -1
  70. package/src/assets/web-panel/assets/{Trust-D_-71Gjt.js → Trust-CeACvTYx.js} +1 -1
  71. package/src/assets/web-panel/assets/{UkeySign-CwjoYze6.js → UkeySign-mDP9EXHq.js} +1 -1
  72. package/src/assets/web-panel/assets/{VideoEditing-BUvHAwqx.js → VideoEditing-veWlKclv.js} +1 -1
  73. package/src/assets/web-panel/assets/{Wallet-Ds-Mgv8V.js → Wallet-Cd2Hheb8.js} +1 -1
  74. package/src/assets/web-panel/assets/{WebAuthn-B1HCLfzA.js → WebAuthn-DyL7ZiHX.js} +1 -1
  75. package/src/assets/web-panel/assets/{WorkflowEditor-BiJ0uOBt.js → WorkflowEditor-C7-7LJH9.js} +1 -1
  76. package/src/assets/web-panel/assets/{chat-CRWoVJL9.js → chat-DXomZMuo.js} +1 -1
  77. package/src/assets/web-panel/assets/{colors-D90H7N7U.js → colors-DlU92QNs.js} +1 -1
  78. package/src/assets/web-panel/assets/{compact-item-C6U27ikN.js → compact-item-sBiTL8mX.js} +1 -1
  79. package/src/assets/web-panel/assets/{createContext-dR8PtJ-p.js → createContext-DZXEnzum.js} +1 -1
  80. package/src/assets/web-panel/assets/{hasIn-CFe-8hdI.js → hasIn-CpCHBZ2M.js} +1 -1
  81. package/src/assets/web-panel/assets/{index-B5fuCdMf.js → index-B0Qbxr57.js} +1 -1
  82. package/src/assets/web-panel/assets/{index-DlIs_MhZ.js → index-B23tuoo9.js} +1 -1
  83. package/src/assets/web-panel/assets/{index-DEEu_VP1.js → index-B3k9UPHc.js} +1 -1
  84. package/src/assets/web-panel/assets/{index-gLrDgd8C.js → index-BK2AFy44.js} +1 -1
  85. package/src/assets/web-panel/assets/{index-_UAOyaYh.js → index-B_-RETt0.js} +1 -1
  86. package/src/assets/web-panel/assets/{index-ml1s2nd5.js → index-BqnhEJls.js} +1 -1
  87. package/src/assets/web-panel/assets/{index-WmmdmN6b.js → index-C52udT0_.js} +3 -3
  88. package/src/assets/web-panel/assets/{index-DrPvpDNw.js → index-C59FgSkU.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-CSIH2KxQ.js → index-C6SDf50u.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-DOW32kkX.js → index-CD3iljXs.js} +1 -1
  91. package/src/assets/web-panel/assets/{index-rhwSri9e.js → index-CDyzZ8_O.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-w5t-vMNO.js → index-CJ7XYa5K.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-zDn5JJTC.js → index-CUe5t5Aa.js} +1 -1
  94. package/src/assets/web-panel/assets/index-CcRX6BlT.js +1 -0
  95. package/src/assets/web-panel/assets/{index-BOOxNqWQ.js → index-ChahjdYE.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-66g2WGdx.js → index-CivbS-57.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CvJ3UZ52.js → index-CjXSvceY.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-5JpRRs-N.js → index-ClN_JuFa.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BWUElbLB.js → index-CwbWZubA.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DN4iOH17.js → index-DKe9jmKG.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-l3oIS_5E.js → index-DUlPMzoM.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CE1ONO_z.js → index-D_IgY63-.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BL7VlSvq.js → index-D_MzScPM.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-Cbm7lyTa.js → index-DeGnHcp5.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-D43N1wTf.js → index-Di1_EQ-X.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-Du2kakr1.js → index-Dj9Nvz6S.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-pOwjlfcg.js → index-Dn8m1d1f.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DibOj-Y8.js → index-Dq5Rn5VS.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-nrBwYuLT.js → index-Dyg6ikIL.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BCKkZgvL.js → index-DygNvCeR.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BKAuW9ip.js → index-F9cBucYf.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-D5x3uBml.js → index-ThrAiEF9.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BCKut9LD.js → index-TwQZkVGh.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-cERDyhbA.js → index-X48zYgZ6.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BbQx_BA_.js → index-XI6772AD.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-cMms0yaN.js → index-_zyXBoS7.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CFbyZ4VS.js → index-ibFHnqHz.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-BZopu374.js → index-s8tvk-fF.js} +1 -1
  119. package/src/assets/web-panel/assets/index-z6h6tqP3.js +1 -0
  120. package/src/assets/web-panel/assets/{initDefaultProps-BYQdbBmy.js → initDefaultProps-DEi92ZnZ.js} +1 -1
  121. package/src/assets/web-panel/assets/{motion-BtpQTgfW.js → motion-BtYKzpOc.js} +1 -1
  122. package/src/assets/web-panel/assets/{move-BXl4Tr-C.js → move-Cb3A1-v-.js} +1 -1
  123. package/src/assets/web-panel/assets/{omit-D83siT_K.js → omit-B6qPDdOf.js} +1 -1
  124. package/src/assets/web-panel/assets/{pickAttrs-DAo4jR1m.js → pickAttrs-DDyeQMUc.js} +1 -1
  125. package/src/assets/web-panel/assets/{placementArrow-BroqhS4u.js → placementArrow-BPV6VO47.js} +1 -1
  126. package/src/assets/web-panel/assets/{responsiveObserve-CQ1ZgLXP.js → responsiveObserve-DJ1ra4dT.js} +1 -1
  127. package/src/assets/web-panel/assets/{slide-tkfTw6kp.js → slide-D6v8tHvB.js} +1 -1
  128. package/src/assets/web-panel/assets/{statusUtils-CGzZbaVH.js → statusUtils-DulKcQLZ.js} +1 -1
  129. package/src/assets/web-panel/assets/{styleChecker-CDEoUvcb.js → styleChecker-Bne7zwMt.js} +1 -1
  130. package/src/assets/web-panel/assets/{useFlexGapSupport-Ba76kVFx.js → useFlexGapSupport-C1miTomM.js} +1 -1
  131. package/src/assets/web-panel/assets/{useFs-B4iO8Fmn.js → useFs-CR-iLa4Z.js} +1 -1
  132. package/src/assets/web-panel/assets/{vnode-vHVV16AJ.js → vnode-yL9axxBy.js} +1 -1
  133. package/src/assets/web-panel/assets/{zoom-DifdtHK7.js → zoom-B-VCMXSD.js} +1 -1
  134. package/src/assets/web-panel/index.html +1 -1
  135. package/src/commands/hub.js +464 -0
  136. package/src/commands/init.js +10 -0
  137. package/src/commands/notification.js +260 -0
  138. package/src/commands/pack.js +319 -0
  139. package/src/commands/persona.js +160 -1
  140. package/src/index.js +4 -0
  141. package/src/lib/packer/pkg-config-generator.js +111 -5
  142. package/src/runtime/agent-core.js +26 -2
  143. package/src/assets/web-panel/assets/index-EFyvtYMT.js +0 -1
  144. package/src/assets/web-panel/assets/index-ohea9DVW.js +0 -1
@@ -132,6 +132,160 @@ export function registerPersonaCommand(program) {
132
132
  logger.log(` Role: ${updated.role || "(no role defined)"}`);
133
133
  });
134
134
 
135
+ // persona list (Phase 3d)
136
+ persona
137
+ .command("list")
138
+ .description(
139
+ "List named personas registered in config.personas (Phase 3d registry)",
140
+ )
141
+ .option("--json", "Emit JSON instead of human-readable", false)
142
+ .action((options) => {
143
+ const projectRoot = findProjectRoot(process.cwd());
144
+ if (!projectRoot) {
145
+ if (options.json) {
146
+ logger.log(
147
+ JSON.stringify({ error: "not in project", code: "NO_PROJECT" }),
148
+ );
149
+ } else {
150
+ logger.error(
151
+ "Not inside a ChainlessChain project. Run `chainlesschain init` first.",
152
+ );
153
+ }
154
+ process.exit(1);
155
+ }
156
+
157
+ const config = loadProjectConfig(projectRoot);
158
+ const personas =
159
+ config?.personas && typeof config.personas === "object"
160
+ ? config.personas
161
+ : {};
162
+ const active = config?.activePersonaName || null;
163
+ const envName = process.env.CC_PACK_AUTO_PERSONA || null;
164
+
165
+ if (options.json) {
166
+ logger.log(
167
+ JSON.stringify(
168
+ {
169
+ activePersonaName: active,
170
+ envPersona: envName,
171
+ personas: Object.fromEntries(
172
+ Object.entries(personas).map(([k, v]) => [
173
+ k,
174
+ { name: v?.name || null, role: v?.role || null },
175
+ ]),
176
+ ),
177
+ hasLegacyInlinePersona: Boolean(config?.persona),
178
+ },
179
+ null,
180
+ 2,
181
+ ),
182
+ );
183
+ return;
184
+ }
185
+
186
+ if (Object.keys(personas).length === 0) {
187
+ logger.log("No named personas registered.");
188
+ if (config?.persona) {
189
+ logger.log(
190
+ chalk.dim(
191
+ " (Legacy inline `config.persona` is set; it activates as the default.)",
192
+ ),
193
+ );
194
+ }
195
+ logger.log(
196
+ `\nAdd one via \`config.personas.<name>\` or by re-running \`cc init -t <template>\` (medical-triage / agriculture-expert / etc.).`,
197
+ );
198
+ return;
199
+ }
200
+
201
+ logger.log(chalk.bold("Registered personas:"));
202
+ for (const [k, v] of Object.entries(personas)) {
203
+ const marker =
204
+ k === envName
205
+ ? chalk.green(" ← CC_PACK_AUTO_PERSONA")
206
+ : k === active
207
+ ? chalk.cyan(" ← active")
208
+ : "";
209
+ logger.log(` ${chalk.cyan(k)}${marker}`);
210
+ if (v?.name) logger.log(` name: ${v.name}`);
211
+ if (v?.role) {
212
+ const oneLine = String(v.role).split("\n")[0].slice(0, 80);
213
+ logger.log(chalk.dim(` role: ${oneLine}`));
214
+ }
215
+ }
216
+ if (envName && !personas[envName]) {
217
+ logger.log(
218
+ chalk.yellow(
219
+ `\n Warning: CC_PACK_AUTO_PERSONA="${envName}" does not match any registered persona.`,
220
+ ),
221
+ );
222
+ }
223
+ });
224
+
225
+ // persona activate (Phase 3d)
226
+ persona
227
+ .command("activate <name>")
228
+ .description(
229
+ "Activate a named persona from config.personas (Phase 3d; equivalent to `cc skill enable` for persona-category skills)",
230
+ )
231
+ .action((name) => {
232
+ const projectRoot = findProjectRoot(process.cwd());
233
+ if (!projectRoot) {
234
+ logger.error(
235
+ "Not inside a ChainlessChain project. Run `chainlesschain init` first.",
236
+ );
237
+ process.exit(1);
238
+ }
239
+
240
+ const configPath = path.join(
241
+ projectRoot,
242
+ ".chainlesschain",
243
+ "config.json",
244
+ );
245
+ let config;
246
+ try {
247
+ config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
248
+ } catch {
249
+ logger.error("Failed to read config.json");
250
+ process.exit(1);
251
+ }
252
+
253
+ const personas =
254
+ config.personas && typeof config.personas === "object"
255
+ ? config.personas
256
+ : {};
257
+ const target = personas[name];
258
+ if (!target) {
259
+ const available = Object.keys(personas);
260
+ logger.error(`No persona named "${name}" in config.personas.`);
261
+ if (available.length > 0) {
262
+ logger.log(`Available: ${chalk.cyan(available.join(", "))}`);
263
+ } else {
264
+ logger.log(
265
+ chalk.dim(
266
+ " (No named personas registered. See `cc persona list` for details.)",
267
+ ),
268
+ );
269
+ }
270
+ process.exit(1);
271
+ }
272
+
273
+ config.activePersonaName = name;
274
+ // Denormalize so `_loadProjectPersona`'s legacy `config.persona` read
275
+ // path also sees the activation. Single source of truth is
276
+ // `activePersonaName`, but the inline copy keeps the resolver
277
+ // backward-compatible without forcing a config-version bump.
278
+ config.persona = target;
279
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
280
+
281
+ logger.success(`Activated persona "${chalk.cyan(name)}".`);
282
+ logger.log(` Display name: ${target.name || "(unnamed)"}`);
283
+ if (target.role) {
284
+ const oneLine = String(target.role).split("\n")[0].slice(0, 80);
285
+ logger.log(chalk.dim(` Role: ${oneLine}`));
286
+ }
287
+ });
288
+
135
289
  // persona reset
136
290
  persona
137
291
  .command("reset")
@@ -160,12 +314,17 @@ export function registerPersonaCommand(program) {
160
314
  process.exit(1);
161
315
  }
162
316
 
163
- if (!config.persona) {
317
+ if (!config.persona && !config.activePersonaName) {
164
318
  logger.log("No persona configured. Nothing to reset.");
165
319
  return;
166
320
  }
167
321
 
168
322
  delete config.persona;
323
+ // Phase 3d: also clear the active-name pointer so _loadProjectPersona
324
+ // doesn't re-resolve through config.personas[activeName]. The personas
325
+ // registry itself is preserved — user can re-activate with `cc persona
326
+ // activate <name>`.
327
+ delete config.activePersonaName;
169
328
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
170
329
  logger.success(
171
330
  "Persona removed. The default coding assistant will be used.",
package/src/index.js CHANGED
@@ -9,11 +9,13 @@ import { registerConfigCommand } from "./commands/config.js";
9
9
  import { registerUpdateCommand } from "./commands/update.js";
10
10
  import { registerDoctorCommand } from "./commands/doctor.js";
11
11
  import { registerPairCommand } from "./commands/pair.js";
12
+ import { registerNotificationCommand } from "./commands/notification.js";
12
13
  import { registerDbCommand } from "./commands/db.js";
13
14
  import { registerNoteCommand } from "./commands/note.js";
14
15
  import { registerChatCommand } from "./commands/chat.js";
15
16
  import { registerAskCommand } from "./commands/ask.js";
16
17
  import { registerLlmCommand } from "./commands/llm.js";
18
+ import { registerHubCommand } from "./commands/hub.js";
17
19
  import {
18
20
  registerAgentCommand,
19
21
  registerSubAgentV2Command,
@@ -395,6 +397,7 @@ export function createProgram(opts = {}) {
395
397
  registerUpdateCommand(program);
396
398
  registerDoctorCommand(program);
397
399
  registerPairCommand(program);
400
+ registerNotificationCommand(program);
398
401
 
399
402
  // Headless commands
400
403
  registerDbCommand(program);
@@ -402,6 +405,7 @@ export function createProgram(opts = {}) {
402
405
  registerChatCommand(program);
403
406
  registerAskCommand(program);
404
407
  registerLlmCommand(program);
408
+ registerHubCommand(program);
405
409
  registerAgentCommand(program);
406
410
  registerSubAgentV2Command(program);
407
411
  registerExecBackendV2Command(program);
@@ -184,35 +184,110 @@ export function generatePkgConfig(ctx) {
184
184
  "// check-update`) can read packedCliVersion / updateManifestUrl without",
185
185
  "// importing from the packer. No-op in CLI-only builds outside pkg.",
186
186
  "globalThis.BAKED = BAKED;",
187
+ "// .env sidecar parser (per design §13 #4). Returns a flat KEY=VALUE",
188
+ "// dict; missing file / unreadable -> {}. Skips blank lines, '#' comments,",
189
+ "// and BOM. Strips matching single/double quote pairs but leaves inner",
190
+ "// content untouched (no escape-sequence interpretation — power users who",
191
+ "// need that can set the var from their shell, which wins anyway).",
192
+ "function _loadDotenv(filePath) {",
193
+ " try {",
194
+ " if (!filePath || !fs.existsSync(filePath)) return {};",
195
+ " const body = fs.readFileSync(filePath, 'utf-8').replace(/^\\uFEFF/, '');",
196
+ " const out = {};",
197
+ " for (const rawLine of body.split(/\\r?\\n/)) {",
198
+ " const line = rawLine.trim();",
199
+ " if (!line || line.startsWith('#')) continue;",
200
+ " const eq = line.indexOf('=');",
201
+ " if (eq <= 0) continue;",
202
+ " const key = line.slice(0, eq).trim();",
203
+ " let val = line.slice(eq + 1).trim();",
204
+ " if (val.length >= 2 &&",
205
+ " ((val.startsWith('\"') && val.endsWith('\"')) ||",
206
+ ' (val.startsWith("\'") && val.endsWith("\'")))) {',
207
+ " val = val.slice(1, -1);",
208
+ " }",
209
+ " out[key] = val;",
210
+ " }",
211
+ " return out;",
212
+ " } catch { return {}; }",
213
+ "}",
214
+ "// Schema-aware deep-merge: bundled (base) values fill in missing keys,",
215
+ "// existing user values win. Used only for .chainlesschain/config.json so",
216
+ "// new exe schema fields land without clobbering user edits.",
217
+ "function _deepMerge(base, override) {",
218
+ " if (override === null || typeof override !== 'object' || Array.isArray(override)) return override;",
219
+ " if (base === null || typeof base !== 'object' || Array.isArray(base)) return override;",
220
+ " const out = { ...base };",
221
+ " for (const k of Object.keys(override)) {",
222
+ " out[k] = (k in base) ? _deepMerge(base[k], override[k]) : override[k];",
223
+ " }",
224
+ " return out;",
225
+ "}",
187
226
  "// Merge-copy helper: copies src tree into dest, skipping files that",
188
227
  "// already exist (preserves user modifications). Used only in project mode.",
189
- "function copyRecursiveMerge(src, dest) {",
228
+ "// Special case: top-level config.json gets deep-merged (user values win,",
229
+ "// bundled supplies new schema fields).",
230
+ "function copyRecursiveMerge(src, dest, rootSrc) {",
231
+ " if (rootSrc === undefined) rootSrc = src;",
190
232
  " if (!fs.existsSync(src)) return;",
191
233
  " fs.mkdirSync(dest, { recursive: true });",
192
234
  " for (const e of fs.readdirSync(src, { withFileTypes: true })) {",
193
235
  " const sp = path.join(src, e.name), dp = path.join(dest, e.name);",
194
- " if (e.isDirectory()) { copyRecursiveMerge(sp, dp); }",
236
+ " if (e.isDirectory()) { copyRecursiveMerge(sp, dp, rootSrc); }",
195
237
  " else if (!fs.existsSync(dp)) { fs.copyFileSync(sp, dp); }",
196
- " else { console.warn('[cc-pack] Keeping existing file (user-modified):', dp); }",
238
+ " else {",
239
+ " const _rel = path.relative(rootSrc, sp).replace(/\\\\/g, '/');",
240
+ " if (_rel === 'config.json') {",
241
+ " try {",
242
+ " const _userCfg = JSON.parse(fs.readFileSync(dp, 'utf-8'));",
243
+ " const _newCfg = JSON.parse(fs.readFileSync(sp, 'utf-8'));",
244
+ " const _merged = _deepMerge(_newCfg, _userCfg);",
245
+ " fs.writeFileSync(dp, JSON.stringify(_merged, null, 2), 'utf-8');",
246
+ " } catch (err) { console.warn('[cc-pack] config.json merge failed, keeping existing:', dp, err && err.message); }",
247
+ " } else {",
248
+ " console.warn('[cc-pack] Keeping existing file (user-modified):', dp);",
249
+ " }",
250
+ " }",
197
251
  " }",
198
252
  "}",
199
253
  "// ── Project mode: materialize bundled .chainlesschain/ to user-data dir ──",
200
254
  "// BAKED.projectMode is absent (falsy) in CLI-only builds — entire block skipped.",
201
255
  "if (BAKED.projectMode) {",
256
+ " // Per design §9: prefer %APPDATA% on Windows (Roaming, ~260-char-safe);",
257
+ " // fall back to ~ on other platforms or when APPDATA is unset.",
258
+ " const _baseDir = (process.platform === 'win32' && process.env.APPDATA)",
259
+ " ? process.env.APPDATA",
260
+ " : os.homedir();",
261
+ " // SHA-16 (64-bit entropy) per design §4.3 — prior SHA-8 had 32-bit entropy",
262
+ " // which is too narrow for multi-project + multi-version coexistence.",
202
263
  " const _userDataDir = path.join(",
203
- " os.homedir(), '.chainlesschain-projects',",
204
- " `${BAKED.projectName}-${BAKED.projectConfigSha.slice(0, 8)}`,",
264
+ " _baseDir, '.chainlesschain-projects',",
265
+ " `${BAKED.projectName}-${BAKED.projectConfigSha.slice(0, 16)}`,",
205
266
  " );",
206
267
  " const _markerFile = path.join(_userDataDir, '.chainlesschain', '.pack-version');",
268
+ " const _lockFile = path.join(_userDataDir, '.chainlesschain', '.materialize.lock');",
207
269
  " const _needsMaterialize =",
208
270
  " BAKED.forceRefreshOnLaunch ||",
209
271
  " !fs.existsSync(_markerFile) ||",
210
272
  " fs.readFileSync(_markerFile, 'utf8').trim() !== BAKED.projectConfigSha;",
273
+ " // Concurrent-materialize protection: only the first instance acquires the",
274
+ " // lock and does the copy. Other instances skip silently — the marker file",
275
+ " // will already be written by the time they get to use the dir.",
276
+ " let _lockFd = null;",
211
277
  " if (_needsMaterialize) {",
278
+ " try {",
279
+ " fs.mkdirSync(path.dirname(_lockFile), { recursive: true });",
280
+ " _lockFd = fs.openSync(_lockFile, 'wx');",
281
+ " } catch { /* another instance holds the lock */ }",
282
+ " }",
283
+ " if (_needsMaterialize && _lockFd !== null) {",
212
284
  " copyRecursiveMerge(BAKED.projectBundledDir, path.join(_userDataDir, '.chainlesschain'));",
213
285
  " fs.mkdirSync(path.dirname(_markerFile), { recursive: true });",
214
286
  " fs.writeFileSync(_markerFile, BAKED.projectConfigSha, 'utf8');",
215
287
  " }",
288
+ " if (_lockFd !== null) {",
289
+ " try { fs.closeSync(_lockFd); fs.unlinkSync(_lockFile); } catch { /* best-effort */ }",
290
+ " }",
216
291
  " process.env.CC_PROJECT_ROOT = _userDataDir;",
217
292
  " if (BAKED.projectAllowedSubcommands) {",
218
293
  " process.env.CC_PROJECT_ALLOWED_SUBCOMMANDS = BAKED.projectAllowedSubcommands.join(',');",
@@ -223,6 +298,25 @@ export function generatePkgConfig(ctx) {
223
298
  " process.env.CC_PACK_AUTO_PERSONA = BAKED.projectAutoPersona;",
224
299
  " }",
225
300
  "}",
301
+ "// Phase 3f: .env sidecar loader (per design §13 #4 + §9 LLM API keys).",
302
+ "// Priority (highest to lowest): explicit process.env (set in shell),",
303
+ "// <CC_PROJECT_ROOT>/.env, <exePath dir>/.env. We snapshot the original",
304
+ "// process.env keys before reading so neither .env can mask a user's",
305
+ "// shell-level export. The userDataDir .env wins over exePath dir when",
306
+ "// both define the same key because we apply it second.",
307
+ "{",
308
+ " const _origEnvKeys = new Set(Object.keys(process.env));",
309
+ " const _exeEnv = _loadDotenv(path.join(path.dirname(process.execPath), '.env'));",
310
+ " const _userEnv = process.env.CC_PROJECT_ROOT",
311
+ " ? _loadDotenv(path.join(process.env.CC_PROJECT_ROOT, '.env'))",
312
+ " : {};",
313
+ " for (const _k of Object.keys(_exeEnv)) {",
314
+ " if (!_origEnvKeys.has(_k)) process.env[_k] = _exeEnv[_k];",
315
+ " }",
316
+ " for (const _k of Object.keys(_userEnv)) {",
317
+ " if (!_origEnvKeys.has(_k)) process.env[_k] = _userEnv[_k];",
318
+ " }",
319
+ "}",
226
320
  "// Double-click from Explorer arrives with no subcommand — without",
227
321
  "// this default, commander prints help and exits, which looks like",
228
322
  "// a black console 'flash and close'. In project mode the baked",
@@ -231,6 +325,18 @@ export function generatePkgConfig(ctx) {
231
325
  "const _hasSub = _rest.some((a) => a && !a.startsWith('-'));",
232
326
  "const _argSet = new Set(_rest);",
233
327
  "const _hasFlag = (...names) => names.some((n) => _argSet.has(n));",
328
+ "// Phase 3f: --version --json short-circuit (per design §13 #3). Plain",
329
+ "// --version goes through commander; the --json combo emits a structured",
330
+ "// payload with cli + (in project mode) project name/sha. We intercept",
331
+ "// before commander.parse so the JSON is the only thing on stdout.",
332
+ "if (_hasFlag('-v', '--version') && _hasFlag('--json')) {",
333
+ " const _vOut = { cli: BAKED.packedCliVersion || 'unknown' };",
334
+ " if (BAKED.projectMode) {",
335
+ " _vOut.project = { name: BAKED.projectName, sha: BAKED.projectConfigSha };",
336
+ " }",
337
+ " console.log(JSON.stringify(_vOut));",
338
+ " process.exit(0);",
339
+ "}",
234
340
  "// Commander short-circuits --version / --help before running any",
235
341
  "// command — don't pollute their stdout with the token banner and",
236
342
  "// baked defaults they'd never see anyway.",
@@ -255,7 +255,18 @@ Current working directory: ${cwd || process.cwd()}`;
255
255
  // ─── Persona support ─────────────────────────────────────────────────────
256
256
 
257
257
  /**
258
- * Load persona configuration from project config.json
258
+ * Load persona configuration from project config.json.
259
+ *
260
+ * Resolution order (highest priority first):
261
+ * 1. CC_PACK_AUTO_PERSONA env var → config.personas[<env>] if present
262
+ * (set by `cc pack --project` packed exe at boot, per Phase 3f; the
263
+ * Phase 3d resolver lives here so packaged products actually activate
264
+ * their bundled persona at runtime)
265
+ * 2. config.activePersonaName → config.personas[<name>] if present
266
+ * (set by `cc persona activate <name>`)
267
+ * 3. config.persona (the legacy inline single-persona shape; still the
268
+ * common case for projects created via `cc init`)
269
+ *
259
270
  * @param {string} cwd - working directory
260
271
  * @returns {object|null} persona object or null
261
272
  */
@@ -264,7 +275,20 @@ function _loadProjectPersona(cwd) {
264
275
  const projectRoot = findProjectRoot(cwd || process.cwd());
265
276
  if (!projectRoot) return null;
266
277
  const config = loadProjectConfig(projectRoot);
267
- return config?.persona || null;
278
+ if (!config) return null;
279
+ const personas =
280
+ config.personas && typeof config.personas === "object"
281
+ ? config.personas
282
+ : null;
283
+ const envName = process.env.CC_PACK_AUTO_PERSONA;
284
+ if (envName && personas && personas[envName]) {
285
+ return personas[envName];
286
+ }
287
+ const activeName = config.activePersonaName;
288
+ if (activeName && personas && personas[activeName]) {
289
+ return personas[activeName];
290
+ }
291
+ return config.persona || null;
268
292
  } catch {
269
293
  return null;
270
294
  }
@@ -1 +0,0 @@
1
- import{C as o}from"./Col-CezPMM8r.js";import{S as t}from"./index-WmmdmN6b.js";import"./index-BbQx_BA_.js";import"./vendor-M5lGV-wr.js";import"./icons-CLQTHa5-.js";const s=t(o);export{s as default};
@@ -1 +0,0 @@
1
- import{A as o}from"./Row-Dsz4KRaU.js";import{S as t}from"./index-WmmdmN6b.js";import"./responsiveObserve-CQ1ZgLXP.js";import"./vendor-M5lGV-wr.js";import"./useFlexGapSupport-Ba76kVFx.js";import"./styleChecker-CDEoUvcb.js";import"./index-BbQx_BA_.js";import"./icons-CLQTHa5-.js";const l=t(o);export{l as default};