@cstack-protocol/pingala 1.0.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 (328) hide show
  1. package/.agent/CSD.md +39 -0
  2. package/.agent/MANIFEST.md +4 -0
  3. package/.agent/MANIFEST.md.template +4 -0
  4. package/.agent/agent-contractor.md +45 -0
  5. package/.agent/architecture/consent-model-fsm.md +77 -0
  6. package/.agent/architecture/governor-maturity-fsm.md +101 -0
  7. package/.agent/architecture/governor-validation-fsm.md +106 -0
  8. package/.agent/architecture/humanized-audit-fsm.md +76 -0
  9. package/.agent/architecture/pingala-csi-fsm.md +81 -0
  10. package/.agent/architecture.md +34 -0
  11. package/.agent/behavior.md +29 -0
  12. package/.agent/compute.md +32 -0
  13. package/.agent/consent-prompts.md +41 -0
  14. package/.agent/governance.yaml +5 -0
  15. package/.agent/identity.md +29 -0
  16. package/.agent/knowledge-lattice.json +96 -0
  17. package/.agent/knowledge-lattice.md +53 -0
  18. package/.agent/lattice-viz.html +157 -0
  19. package/.agent/mission.md +37 -0
  20. package/.agent/pairing-protocol.md +89 -0
  21. package/.agent/pairing.csp +108 -0
  22. package/.agent/personas/reflective-operator.md +67 -0
  23. package/.agent/personas/research.md +62 -0
  24. package/.agent/pingala.md +47 -0
  25. package/.agent/roadmap.md +56 -0
  26. package/.agent/scripts/lattice-extract.py +100 -0
  27. package/.agent/scripts/sync-agents.sh +82 -0
  28. package/.agent/scripts/vault-ingest.py +80 -0
  29. package/.agent/seo-strategy.md +71 -0
  30. package/.agent/skills/agent-orchestrator/SKILL.md +22 -0
  31. package/.agent/skills/agent-orchestrator/scripts/sync-agents.sh +61 -0
  32. package/.agent/skills/knowledge-lattice/SKILL.md +23 -0
  33. package/.agent/skills/knowledge-lattice/scripts/lattice-extract.py +107 -0
  34. package/.agent/skills/resource-vault/SKILL.md +30 -0
  35. package/.agent/skills/resource-vault/scripts/vault-ingest.py +80 -0
  36. package/.agent/skills/sites-integrity/SKILL.md +28 -0
  37. package/.agent/skills/stack-auditor/SKILL.md +25 -0
  38. package/.agent/sources.md +20 -0
  39. package/.agent/stack-auditor.md +47 -0
  40. package/.agent/standards.md +36 -0
  41. package/.agent/strategy.md +65 -0
  42. package/.agent/vault-schema.md +53 -0
  43. package/.agent/voice.md +27 -0
  44. package/.agent/workflows/sync-agents.md +14 -0
  45. package/.env.example +5 -0
  46. package/.env.production +3 -0
  47. package/DISTRIBUTION-PLAN.md +33 -0
  48. package/HOSTED_SETUP.md +54 -0
  49. package/LANDING_PAGE_DESIGN.md +46 -0
  50. package/MANUAL_VERCEL_STEPS.md +39 -0
  51. package/PRODUCT-ROADMAP.md +241 -0
  52. package/PROVISIONING_GUIDE.md +39 -0
  53. package/README.md +38 -0
  54. package/ROADMAP.md +21 -0
  55. package/SYNC-ENGINE-SPEC.md +257 -0
  56. package/build/core/531-protocol.d.ts +26 -0
  57. package/build/core/531-protocol.js +87 -0
  58. package/build/core/531-protocol.js.map +1 -0
  59. package/build/core/531-rule.d.ts +26 -0
  60. package/build/core/531-rule.js +106 -0
  61. package/build/core/531-rule.js.map +1 -0
  62. package/build/core/auth.d.ts +1 -0
  63. package/build/core/auth.js +24 -0
  64. package/build/core/auth.js.map +1 -0
  65. package/build/core/consent-manager.d.ts +17 -0
  66. package/build/core/consent-manager.js +104 -0
  67. package/build/core/consent-manager.js.map +1 -0
  68. package/build/core/csp.d.ts +12 -0
  69. package/build/core/csp.js +20 -0
  70. package/build/core/csp.js.map +1 -0
  71. package/build/core/engagement-analyzer.d.ts +42 -0
  72. package/build/core/engagement-analyzer.js +71 -0
  73. package/build/core/engagement-analyzer.js.map +1 -0
  74. package/build/core/governor.d.ts +106 -0
  75. package/build/core/governor.js +405 -0
  76. package/build/core/governor.js.map +1 -0
  77. package/build/core/life-area-mapper.d.ts +39 -0
  78. package/build/core/life-area-mapper.js +73 -0
  79. package/build/core/life-area-mapper.js.map +1 -0
  80. package/build/core/methodology.d.ts +39 -0
  81. package/build/core/methodology.js +164 -0
  82. package/build/core/methodology.js.map +1 -0
  83. package/build/core/pingala.d.ts +31 -0
  84. package/build/core/pingala.js +56 -0
  85. package/build/core/pingala.js.map +1 -0
  86. package/build/core/sdk-adapter.d.ts +6 -0
  87. package/build/core/sdk-adapter.js +33 -0
  88. package/build/core/sdk-adapter.js.map +1 -0
  89. package/build/cs-agent-core/sdk/index.d.ts +6 -0
  90. package/build/cs-agent-core/sdk/index.js +18 -0
  91. package/build/cs-agent-core/sdk/index.js.map +1 -0
  92. package/build/cs-agent-core/sdk/patterns/index.d.ts +3 -0
  93. package/build/cs-agent-core/sdk/patterns/index.js +37 -0
  94. package/build/cs-agent-core/sdk/patterns/index.js.map +1 -0
  95. package/build/cs-agent-core/sdk/patterns/registry.d.ts +4 -0
  96. package/build/cs-agent-core/sdk/patterns/registry.js +80 -0
  97. package/build/cs-agent-core/sdk/patterns/registry.js.map +1 -0
  98. package/build/cs-agent-core/sdk/telemetry/buffer.d.ts +9 -0
  99. package/build/cs-agent-core/sdk/telemetry/buffer.js +47 -0
  100. package/build/cs-agent-core/sdk/telemetry/buffer.js.map +1 -0
  101. package/build/cs-agent-core/sdk/telemetry/scrubber.d.ts +3 -0
  102. package/build/cs-agent-core/sdk/telemetry/scrubber.js +13 -0
  103. package/build/cs-agent-core/sdk/telemetry/scrubber.js.map +1 -0
  104. package/build/cs-agent-core/sdk/telemetry/types.d.ts +50 -0
  105. package/build/cs-agent-core/sdk/telemetry/types.js +2 -0
  106. package/build/cs-agent-core/sdk/telemetry/types.js.map +1 -0
  107. package/build/cs-agent-core/sdk/types/decision.d.ts +18 -0
  108. package/build/cs-agent-core/sdk/types/decision.js +2 -0
  109. package/build/cs-agent-core/sdk/types/decision.js.map +1 -0
  110. package/build/cs-agent-core/sdk/types/index.d.ts +4 -0
  111. package/build/cs-agent-core/sdk/types/index.js +5 -0
  112. package/build/cs-agent-core/sdk/types/index.js.map +1 -0
  113. package/build/cs-agent-core/sdk/types/pattern.d.ts +17 -0
  114. package/build/cs-agent-core/sdk/types/pattern.js +2 -0
  115. package/build/cs-agent-core/sdk/types/pattern.js.map +1 -0
  116. package/build/cs-agent-core/sdk/types/stack.d.ts +8 -0
  117. package/build/cs-agent-core/sdk/types/stack.js +2 -0
  118. package/build/cs-agent-core/sdk/types/stack.js.map +1 -0
  119. package/build/cs-agent-core/sdk/types/tool.d.ts +9 -0
  120. package/build/cs-agent-core/sdk/types/tool.js +2 -0
  121. package/build/cs-agent-core/sdk/types/tool.js.map +1 -0
  122. package/build/cs-agent-core/sdk/validator/csi.d.ts +2 -0
  123. package/build/cs-agent-core/sdk/validator/csi.js +24 -0
  124. package/build/cs-agent-core/sdk/validator/csi.js.map +1 -0
  125. package/build/cs-agent-core/sdk/validator/index.d.ts +2 -0
  126. package/build/cs-agent-core/sdk/validator/index.js +3 -0
  127. package/build/cs-agent-core/sdk/validator/index.js.map +1 -0
  128. package/build/cs-agent-core/sdk/validator/rules/geometry.d.ts +11 -0
  129. package/build/cs-agent-core/sdk/validator/rules/geometry.js +22 -0
  130. package/build/cs-agent-core/sdk/validator/rules/geometry.js.map +1 -0
  131. package/build/cs-agent-core/sdk/validator/validate.d.ts +2 -0
  132. package/build/cs-agent-core/sdk/validator/validate.js +46 -0
  133. package/build/cs-agent-core/sdk/validator/validate.js.map +1 -0
  134. package/build/index.d.ts +2 -0
  135. package/build/index.js +444 -0
  136. package/build/index.js.map +1 -0
  137. package/build/pingala-mcp/src/core/531-rule.d.ts +26 -0
  138. package/build/pingala-mcp/src/core/531-rule.js +96 -0
  139. package/build/pingala-mcp/src/core/531-rule.js.map +1 -0
  140. package/build/pingala-mcp/src/core/auth.d.ts +1 -0
  141. package/build/pingala-mcp/src/core/auth.js +15 -0
  142. package/build/pingala-mcp/src/core/auth.js.map +1 -0
  143. package/build/pingala-mcp/src/core/consent-manager.d.ts +17 -0
  144. package/build/pingala-mcp/src/core/consent-manager.js +104 -0
  145. package/build/pingala-mcp/src/core/consent-manager.js.map +1 -0
  146. package/build/pingala-mcp/src/core/csp.d.ts +12 -0
  147. package/build/pingala-mcp/src/core/csp.js +20 -0
  148. package/build/pingala-mcp/src/core/csp.js.map +1 -0
  149. package/build/pingala-mcp/src/core/engagement-analyzer.d.ts +42 -0
  150. package/build/pingala-mcp/src/core/engagement-analyzer.js +71 -0
  151. package/build/pingala-mcp/src/core/engagement-analyzer.js.map +1 -0
  152. package/build/pingala-mcp/src/core/governor.d.ts +104 -0
  153. package/build/pingala-mcp/src/core/governor.js +359 -0
  154. package/build/pingala-mcp/src/core/governor.js.map +1 -0
  155. package/build/pingala-mcp/src/core/life-area-mapper.d.ts +39 -0
  156. package/build/pingala-mcp/src/core/life-area-mapper.js +73 -0
  157. package/build/pingala-mcp/src/core/life-area-mapper.js.map +1 -0
  158. package/build/pingala-mcp/src/core/methodology.d.ts +39 -0
  159. package/build/pingala-mcp/src/core/methodology.js +164 -0
  160. package/build/pingala-mcp/src/core/methodology.js.map +1 -0
  161. package/build/pingala-mcp/src/core/pingala.d.ts +25 -0
  162. package/build/pingala-mcp/src/core/pingala.js +56 -0
  163. package/build/pingala-mcp/src/core/pingala.js.map +1 -0
  164. package/build/pingala-mcp/src/core/sdk-adapter.d.ts +6 -0
  165. package/build/pingala-mcp/src/core/sdk-adapter.js +33 -0
  166. package/build/pingala-mcp/src/core/sdk-adapter.js.map +1 -0
  167. package/build/pingala-mcp/src/index.d.ts +1 -0
  168. package/build/pingala-mcp/src/index.js +221 -0
  169. package/build/pingala-mcp/src/index.js.map +1 -0
  170. package/build/pingala-mcp/src/test-l3.d.ts +1 -0
  171. package/build/pingala-mcp/src/test-l3.js +35 -0
  172. package/build/pingala-mcp/src/test-l3.js.map +1 -0
  173. package/build/pingala-mcp/src/tools/audit-workspace.d.ts +16 -0
  174. package/build/pingala-mcp/src/tools/audit-workspace.js +39 -0
  175. package/build/pingala-mcp/src/tools/audit-workspace.js.map +1 -0
  176. package/build/pingala-mcp/src/tools/calculate-csi.d.ts +24 -0
  177. package/build/pingala-mcp/src/tools/calculate-csi.js +29 -0
  178. package/build/pingala-mcp/src/tools/calculate-csi.js.map +1 -0
  179. package/build/pingala-mcp/src/tools/cs-audit.d.ts +54 -0
  180. package/build/pingala-mcp/src/tools/cs-audit.js +310 -0
  181. package/build/pingala-mcp/src/tools/cs-audit.js.map +1 -0
  182. package/build/pingala-mcp/src/tools/get-governance-context.d.ts +11 -0
  183. package/build/pingala-mcp/src/tools/get-governance-context.js +16 -0
  184. package/build/pingala-mcp/src/tools/get-governance-context.js.map +1 -0
  185. package/build/pingala-mcp/src/tools/validate-stack-change.d.ts +41 -0
  186. package/build/pingala-mcp/src/tools/validate-stack-change.js +35 -0
  187. package/build/pingala-mcp/src/tools/validate-stack-change.js.map +1 -0
  188. package/build/sdk/index.d.ts +6 -0
  189. package/build/sdk/index.js +18 -0
  190. package/build/sdk/index.js.map +1 -0
  191. package/build/sdk/patterns/index.d.ts +3 -0
  192. package/build/sdk/patterns/index.js +37 -0
  193. package/build/sdk/patterns/index.js.map +1 -0
  194. package/build/sdk/patterns/registry.d.ts +4 -0
  195. package/build/sdk/patterns/registry.js +80 -0
  196. package/build/sdk/patterns/registry.js.map +1 -0
  197. package/build/sdk/telemetry/buffer.d.ts +9 -0
  198. package/build/sdk/telemetry/buffer.js +47 -0
  199. package/build/sdk/telemetry/buffer.js.map +1 -0
  200. package/build/sdk/telemetry/scrubber.d.ts +3 -0
  201. package/build/sdk/telemetry/scrubber.js +13 -0
  202. package/build/sdk/telemetry/scrubber.js.map +1 -0
  203. package/build/sdk/telemetry/types.d.ts +50 -0
  204. package/build/sdk/telemetry/types.js +2 -0
  205. package/build/sdk/telemetry/types.js.map +1 -0
  206. package/build/sdk/types/decision.d.ts +18 -0
  207. package/build/sdk/types/decision.js +2 -0
  208. package/build/sdk/types/decision.js.map +1 -0
  209. package/build/sdk/types/index.d.ts +4 -0
  210. package/build/sdk/types/index.js +5 -0
  211. package/build/sdk/types/index.js.map +1 -0
  212. package/build/sdk/types/pattern.d.ts +17 -0
  213. package/build/sdk/types/pattern.js +2 -0
  214. package/build/sdk/types/pattern.js.map +1 -0
  215. package/build/sdk/types/stack.d.ts +8 -0
  216. package/build/sdk/types/stack.js +2 -0
  217. package/build/sdk/types/stack.js.map +1 -0
  218. package/build/sdk/types/tool.d.ts +9 -0
  219. package/build/sdk/types/tool.js +2 -0
  220. package/build/sdk/types/tool.js.map +1 -0
  221. package/build/sdk/validator/csi.d.ts +2 -0
  222. package/build/sdk/validator/csi.js +24 -0
  223. package/build/sdk/validator/csi.js.map +1 -0
  224. package/build/sdk/validator/index.d.ts +2 -0
  225. package/build/sdk/validator/index.js +3 -0
  226. package/build/sdk/validator/index.js.map +1 -0
  227. package/build/sdk/validator/rules/geometry.d.ts +11 -0
  228. package/build/sdk/validator/rules/geometry.js +22 -0
  229. package/build/sdk/validator/rules/geometry.js.map +1 -0
  230. package/build/sdk/validator/validate.d.ts +2 -0
  231. package/build/sdk/validator/validate.js +46 -0
  232. package/build/sdk/validator/validate.js.map +1 -0
  233. package/build/src/core/531-rule.d.ts +26 -0
  234. package/build/src/core/531-rule.js +96 -0
  235. package/build/src/core/531-rule.js.map +1 -0
  236. package/build/src/core/auth.d.ts +1 -0
  237. package/build/src/core/auth.js +15 -0
  238. package/build/src/core/auth.js.map +1 -0
  239. package/build/src/core/consent-manager.d.ts +17 -0
  240. package/build/src/core/consent-manager.js +104 -0
  241. package/build/src/core/consent-manager.js.map +1 -0
  242. package/build/src/core/csp.d.ts +12 -0
  243. package/build/src/core/csp.js +20 -0
  244. package/build/src/core/csp.js.map +1 -0
  245. package/build/src/core/engagement-analyzer.d.ts +42 -0
  246. package/build/src/core/engagement-analyzer.js +71 -0
  247. package/build/src/core/engagement-analyzer.js.map +1 -0
  248. package/build/src/core/governor.d.ts +104 -0
  249. package/build/src/core/governor.js +371 -0
  250. package/build/src/core/governor.js.map +1 -0
  251. package/build/src/core/life-area-mapper.d.ts +39 -0
  252. package/build/src/core/life-area-mapper.js +73 -0
  253. package/build/src/core/life-area-mapper.js.map +1 -0
  254. package/build/src/core/methodology.d.ts +39 -0
  255. package/build/src/core/methodology.js +164 -0
  256. package/build/src/core/methodology.js.map +1 -0
  257. package/build/src/core/pingala.d.ts +25 -0
  258. package/build/src/core/pingala.js +56 -0
  259. package/build/src/core/pingala.js.map +1 -0
  260. package/build/src/core/sdk-adapter.d.ts +8 -0
  261. package/build/src/core/sdk-adapter.js +34 -0
  262. package/build/src/core/sdk-adapter.js.map +1 -0
  263. package/build/src/index.d.ts +2 -0
  264. package/build/src/index.js +333 -0
  265. package/build/src/index.js.map +1 -0
  266. package/build/src/test-l3.d.ts +1 -0
  267. package/build/src/test-l3.js +35 -0
  268. package/build/src/test-l3.js.map +1 -0
  269. package/build/src/tools/audit-workspace.d.ts +16 -0
  270. package/build/src/tools/audit-workspace.js +39 -0
  271. package/build/src/tools/audit-workspace.js.map +1 -0
  272. package/build/src/tools/calculate-csi.d.ts +24 -0
  273. package/build/src/tools/calculate-csi.js +29 -0
  274. package/build/src/tools/calculate-csi.js.map +1 -0
  275. package/build/src/tools/cs-audit.d.ts +54 -0
  276. package/build/src/tools/cs-audit.js +310 -0
  277. package/build/src/tools/cs-audit.js.map +1 -0
  278. package/build/src/tools/get-governance-context.d.ts +11 -0
  279. package/build/src/tools/get-governance-context.js +16 -0
  280. package/build/src/tools/get-governance-context.js.map +1 -0
  281. package/build/src/tools/validate-stack-change.d.ts +41 -0
  282. package/build/src/tools/validate-stack-change.js +35 -0
  283. package/build/src/tools/validate-stack-change.js.map +1 -0
  284. package/build/test-l3.d.ts +1 -0
  285. package/build/test-l3.js +35 -0
  286. package/build/test-l3.js.map +1 -0
  287. package/build/tools/analyze-stack.d.ts +40 -0
  288. package/build/tools/analyze-stack.js +121 -0
  289. package/build/tools/analyze-stack.js.map +1 -0
  290. package/build/tools/audit-workspace.d.ts +16 -0
  291. package/build/tools/audit-workspace.js +39 -0
  292. package/build/tools/audit-workspace.js.map +1 -0
  293. package/build/tools/calculate-csi.d.ts +26 -0
  294. package/build/tools/calculate-csi.js +30 -0
  295. package/build/tools/calculate-csi.js.map +1 -0
  296. package/build/tools/cs-audit.d.ts +43 -0
  297. package/build/tools/cs-audit.js +330 -0
  298. package/build/tools/cs-audit.js.map +1 -0
  299. package/build/tools/get-governance-context.d.ts +11 -0
  300. package/build/tools/get-governance-context.js +61 -0
  301. package/build/tools/get-governance-context.js.map +1 -0
  302. package/build/tools/validate-stack-change.d.ts +41 -0
  303. package/build/tools/validate-stack-change.js +54 -0
  304. package/build/tools/validate-stack-change.js.map +1 -0
  305. package/package.json +34 -0
  306. package/scripts/cloud-bridge.js +62 -0
  307. package/scripts/generate-token.js +13 -0
  308. package/src/core/531-rule.ts +148 -0
  309. package/src/core/auth.ts +42 -0
  310. package/src/core/consent-manager.ts +134 -0
  311. package/src/core/csp.ts +40 -0
  312. package/src/core/engagement-analyzer.ts +122 -0
  313. package/src/core/governor.ts +522 -0
  314. package/src/core/life-area-mapper.ts +138 -0
  315. package/src/core/methodology.ts +256 -0
  316. package/src/core/pingala.ts +77 -0
  317. package/src/core/sdk-adapter.ts +52 -0
  318. package/src/index.ts +562 -0
  319. package/src/test-l3.ts +45 -0
  320. package/src/tools/analyze-stack.ts +153 -0
  321. package/src/tools/audit-workspace.ts +50 -0
  322. package/src/tools/calculate-csi.ts +38 -0
  323. package/src/tools/cs-audit.ts +384 -0
  324. package/src/tools/get-governance-context.ts +69 -0
  325. package/src/tools/validate-stack-change.ts +71 -0
  326. package/src/types.d.ts +2 -0
  327. package/tsconfig.json +40 -0
  328. package/vercel.json +15 -0
@@ -0,0 +1,522 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import * as os from "node:os";
4
+ import process from "node:process";
5
+ import { Rule531, type ToolInstance } from "./531-rule.js";
6
+
7
+ export interface MaturityState {
8
+ level: number;
9
+ level_name: string;
10
+ stability_days: number;
11
+ last_changed_at: string; // ISO date
12
+ readonly?: boolean; // If true, state cannot be persisted (e.g. cloud/stateless mode)
13
+ definition?: string;
14
+ primary_action?: string;
15
+ telemetry?: {
16
+ attention_depth: number; // 0-100
17
+ dependency_exposure: number; // 0-100
18
+ last_updated: string;
19
+ };
20
+ decision_stats?: {
21
+ total_validations: number;
22
+ justified_validations: number;
23
+ };
24
+ csi_baseline?: number;
25
+ csi_latest?: number;
26
+ }
27
+
28
+ export interface ProposedChange {
29
+ type: 'add_tool' | 'remove_tool' | 'change_role' | 'change_anchor' | 'audit';
30
+ tool_name: string;
31
+ proposed_role?: 'Anchor' | 'Active' | 'Supporting';
32
+ functionId?: string; // Horizon 1.5: Functional Slot/Room ID
33
+ contexts?: string[]; // Horizon 1.5: System contexts
34
+ isAdapter?: boolean; // Horizon 1.5: Bridge Coefficient flag
35
+ replaces_existing?: boolean;
36
+ replaced_tool?: string;
37
+ justification?: string;
38
+ }
39
+
40
+ export interface GovernanceContext {
41
+ current_stack: {
42
+ anchor: ToolInstance | null;
43
+ active: ToolInstance[];
44
+ supporting: ToolInstance[];
45
+ };
46
+ functional_nodes: {
47
+ id: string;
48
+ role: string;
49
+ tools: string[];
50
+ }[];
51
+ maturity_level: number;
52
+ maturity_name: string;
53
+ stability_days: number;
54
+ csi_latest: number;
55
+ allowed_actions: string[];
56
+ blocked_actions: string[];
57
+ progression: {
58
+ can_level_up: boolean;
59
+ next_level: number | null;
60
+ days_remaining: number;
61
+ csi_delta: number;
62
+ is_l2_eligible: boolean;
63
+ };
64
+ }
65
+
66
+ export class Governor {
67
+ private static dataDir: string = (() => {
68
+ if (process.env.CSTACK_DATA_DIR) return process.env.CSTACK_DATA_DIR;
69
+ if (process.env.VERCEL) return "/tmp";
70
+ return path.join(os.homedir(), ".cstack-data");
71
+ })();
72
+
73
+ private static getFilePath(filename: string): string {
74
+ try {
75
+ if (!fs.existsSync(this.dataDir)) {
76
+ fs.mkdirSync(this.dataDir, { recursive: true });
77
+ }
78
+ } catch (e) {
79
+ console.error(`[Governor] Warning: Could not create data directory ${this.dataDir}. Using /tmp fallback.`);
80
+ this.dataDir = "/tmp";
81
+ }
82
+ return path.join(this.dataDir, filename);
83
+ }
84
+
85
+ private static DEFAULT_STACK: ToolInstance[] = [
86
+ { name: "Pingala", role: "Anchor", functionId: "Core-Governance", category: "Core" },
87
+ { name: "Claude", role: "Active", functionId: "Interaction-Edge", category: "AI" },
88
+ { name: "Vercel", role: "Active", functionId: "Cloud-Compute", category: "Infrastructure" },
89
+ { name: "Cursor", role: "Active", functionId: "Development-Lattice", category: "IDE" },
90
+ { name: "Express", role: "Supporting", functionId: "Transport-Node", category: "Web" },
91
+ { name: "MCP-SDK", role: "Supporting", functionId: "Protocol-Core", category: "Library" },
92
+ { name: "Zod", role: "Supporting", functionId: "Schema-Guardian", category: "Validation" },
93
+ { name: "TypeScript", role: "Supporting", functionId: "Logic-Lattice", category: "Logic" },
94
+ { name: "Git", role: "Supporting", functionId: "Source-History", category: "VCS" }
95
+ ];
96
+
97
+ static getStack(): ToolInstance[] {
98
+ const filePath = this.getFilePath("stack-map.json");
99
+ // If we are in fallback /tmp, check if we have persistence
100
+ if (this.dataDir === "/tmp" && !process.env.VERCEL) {
101
+ // Local fallback without permissions = readonly default
102
+ }
103
+
104
+ if (fs.existsSync(filePath)) {
105
+ try {
106
+ const data = JSON.parse(fs.readFileSync(filePath, "utf-8"));
107
+ return data.tools || this.DEFAULT_STACK;
108
+ } catch (e) {
109
+ console.error("[Governor] Error reading stack-map.json:", e);
110
+ return this.DEFAULT_STACK;
111
+ }
112
+ }
113
+ return this.DEFAULT_STACK;
114
+ }
115
+
116
+ static saveStack(tools: ToolInstance[]): void {
117
+ const state = this.getMaturityState();
118
+ if (state.readonly) return; // Skip persistence in stateless mode
119
+
120
+ const filePath = this.getFilePath("stack-map.json");
121
+ try {
122
+ fs.writeFileSync(filePath, JSON.stringify({ tools }, null, 2));
123
+
124
+ // Update stability
125
+ state.last_changed_at = new Date().toISOString();
126
+ this.saveMaturityState(state);
127
+ } catch (e) {
128
+ console.error("[Governor] Warning: Could not save stack-map.json", e);
129
+ }
130
+ }
131
+
132
+ static getMaturityState(): MaturityState {
133
+ const filePath = this.getFilePath("maturity-state.json");
134
+ const defaultState: MaturityState = {
135
+ level: 1,
136
+ level_name: "Fragmented",
137
+ stability_days: 0,
138
+ last_changed_at: new Date().toISOString(),
139
+ readonly: this.dataDir === "/tmp" && process.env.NODE_ENV === "production"
140
+ };
141
+
142
+ if (fs.existsSync(filePath)) {
143
+ try {
144
+ const state = JSON.parse(fs.readFileSync(filePath, "utf-8"));
145
+
146
+ // Calculate actual stability days
147
+ const lastChanged = new Date(state.last_changed_at);
148
+ const now = new Date();
149
+ const diffTime = Math.abs(now.getTime() - lastChanged.getTime());
150
+ state.stability_days = Math.floor(diffTime / (1000 * 60 * 60 * 24));
151
+
152
+ return state;
153
+ } catch (e) {
154
+ console.error("[Governor] Error reading maturity-state.json:", e);
155
+ return defaultState;
156
+ }
157
+ }
158
+ return defaultState;
159
+ }
160
+
161
+ static saveMaturityState(state: MaturityState): void {
162
+ if (state.readonly) return; // Skip persistence in stateless mode
163
+
164
+ const filePath = this.getFilePath("maturity-state.json");
165
+ try {
166
+ fs.writeFileSync(filePath, JSON.stringify(state, null, 2));
167
+ } catch (e) {
168
+ console.error("[Governor] Warning: Could not save maturity state", e);
169
+ }
170
+ }
171
+
172
+ static recordTelemetry(data: { attention_depth?: number; dependency_exposure?: number }): void {
173
+ const state = this.getMaturityState();
174
+ if (state.readonly) return;
175
+
176
+ state.telemetry = {
177
+ attention_depth: data.attention_depth ?? state.telemetry?.attention_depth ?? 50,
178
+ dependency_exposure: data.dependency_exposure ?? state.telemetry?.dependency_exposure ?? 50,
179
+ last_updated: new Date().toISOString()
180
+ };
181
+ this.saveMaturityState(state);
182
+ }
183
+
184
+ static recordValidation(justified: boolean): void {
185
+ const state = this.getMaturityState();
186
+ if (state.readonly) return;
187
+
188
+ if (!state.decision_stats) {
189
+ state.decision_stats = { total_validations: 0, justified_validations: 0 };
190
+ }
191
+ state.decision_stats.total_validations++;
192
+ if (justified) state.decision_stats.justified_validations++;
193
+ this.saveMaturityState(state);
194
+ }
195
+
196
+ static updateCsi(score: number): void {
197
+ const state = this.getMaturityState();
198
+ if (state.readonly) return;
199
+
200
+ if (state.csi_baseline === undefined) {
201
+ state.csi_baseline = score;
202
+ }
203
+ state.csi_latest = score;
204
+ this.saveMaturityState(state);
205
+ }
206
+
207
+ static getDecisionProvenanceScore(): number {
208
+ const state = this.getMaturityState();
209
+ if (!state.decision_stats || state.decision_stats.total_validations === 0) return 50;
210
+ return Math.round((state.decision_stats.justified_validations / state.decision_stats.total_validations) * 100);
211
+ }
212
+
213
+ static getStackDriftScore(): { score: number; signals: string[]; summary: string } {
214
+ const tools = this.getStack();
215
+ const state = this.getMaturityState();
216
+ const validation = Rule531.validate({ tools });
217
+
218
+ let score = validation.score;
219
+ const signals = [...validation.violations];
220
+
221
+ // Temporal deductions
222
+ const lastChanged = new Date(state.last_changed_at);
223
+ const now = new Date();
224
+ const diffDays = Math.floor(Math.abs(now.getTime() - lastChanged.getTime()) / (1000 * 60 * 60 * 24));
225
+
226
+ if (diffDays > 0) {
227
+ const temporalPenalty = Math.min(20, diffDays * 5);
228
+ score -= temporalPenalty;
229
+ if (temporalPenalty > 0) {
230
+ signals.push(`Attention Erosion: ${diffDays} days since last protocol synthesis (-${temporalPenalty} points)`);
231
+ }
232
+ }
233
+
234
+ // Anchor check (specifically for drift signal)
235
+ if (!tools.some(t => t.role === 'Anchor')) {
236
+ // Rule531 might already have this in recommendations, but let's ensure it impacts score/signals
237
+ if (!signals.some(s => s.includes("Anchor"))) {
238
+ score -= 10;
239
+ signals.push("Anchor Void: No center of truth established (-10 points)");
240
+ }
241
+ }
242
+
243
+ score = Math.max(0, score);
244
+
245
+ let summary = "Maintaining Crystalline Geometry.";
246
+ if (score < 85) summary = "Minor drift detected. Review Supporting nodes.";
247
+ if (score < 70) summary = "Significant architectural erosion. Audit required.";
248
+ if (score < 50) summary = "Systemic collapse risk. Execute rapid reversal.";
249
+
250
+ return { score, signals, summary };
251
+ }
252
+
253
+ static validateStackChange(change: ProposedChange, stackOverride?: ToolInstance[]) {
254
+ const currentStack = stackOverride || this.getStack();
255
+ const state = this.getMaturityState();
256
+
257
+ // Rule 1: 5:3:1 Enforcement
258
+ const validation = this.check531Rules(currentStack, change);
259
+ if (!validation.allowed) return validation;
260
+
261
+ // Rule 3: Maturity Gates
262
+ const gate = this.enforceMaturityGates(state, change);
263
+ if (!gate.allowed) return gate;
264
+
265
+ return {
266
+ allowed: true,
267
+ reason: "Compliant with the Conscious Stack Protocol (CSP) and Maturity Gates",
268
+ impact: {
269
+ stability_reset: true,
270
+ new_stability_days: 0
271
+ }
272
+ };
273
+ }
274
+
275
+ private static check531Rules(currentStack: ToolInstance[], change: ProposedChange) {
276
+ const getRoleNodeCount = (tools: ToolInstance[], role: string) => {
277
+ const roleTools = tools.filter(t => t.role === role);
278
+ // In Fractal logic, a core role is only counted if it represents a UNIQUE slot
279
+ // UNLESS it's an anchor of a sub-stack that is being promoted to a higher stack.
280
+ const slots = new Set(roleTools.filter(t => t.functionId).map(t => t.functionId));
281
+ const unclassifiedCount = roleTools.filter(t => !t.functionId).length;
282
+ return slots.size + unclassifiedCount;
283
+ };
284
+
285
+ const counts = {
286
+ anchor: getRoleNodeCount(currentStack, 'Anchor'),
287
+ active: getRoleNodeCount(currentStack, 'Active'),
288
+ supporting: getRoleNodeCount(currentStack, 'Supporting')
289
+ };
290
+
291
+ if (change.type === 'add_tool' || change.type === 'change_role') {
292
+ const role = change.proposed_role;
293
+ const targetFunctionId = change.functionId;
294
+
295
+ // Check if this tool is being added to an EXISTING functional node (Fractal Slot)
296
+ const existingNodeTools = targetFunctionId ? currentStack.filter(t => t.functionId === targetFunctionId) : [];
297
+ const isSubstack = existingNodeTools.length > 0;
298
+
299
+ if (isSubstack) {
300
+ // FRACTAL RULE: If adding to a sub-stack, check if we are creating a Sub-stack Anchor conflict
301
+ if (role === 'Anchor' && existingNodeTools.some(t => t.role === 'Anchor')) {
302
+ const currentSubAnchor = existingNodeTools.find(t => t.role === 'Anchor');
303
+ return {
304
+ allowed: false,
305
+ reason: `Fractal Violation: Sub-stack '${targetFunctionId}' already has an Anchor (${currentSubAnchor?.name}). Only one tool can be the 'Visible' gateway for this slot.`,
306
+ alternatives: [
307
+ `Demote ${change.tool_name} to Supporting within the ${targetFunctionId} sub-stack`,
308
+ `Replace ${currentSubAnchor?.name} as the primary gateway for this slot`
309
+ ]
310
+ };
311
+ }
312
+
313
+ // If the sub-stack currently HAS NO anchor, and we are adding a non-anchor, warn but allow (will trigger audit violation)
314
+ return { allowed: true };
315
+ }
316
+
317
+ // CORE STACK LIMITS (Slot-based)
318
+ if (role === 'Anchor') {
319
+ if (counts.anchor >= 1 && !change.replaces_existing) {
320
+ const currentAnchor = currentStack.find(t => t.role === 'Anchor');
321
+ return {
322
+ allowed: false,
323
+ reason: `Protocol violation: Only 1 Anchor Node permitted in the Core Stack. Current anchor: ${currentAnchor?.name}`,
324
+ alternatives: [
325
+ `Cluster ${change.tool_name} into the existing Anchor slot (building a sub-stack)`,
326
+ `Replace ${currentAnchor?.name} with ${change.tool_name}`,
327
+ `Assign ${change.tool_name} as Active instead`
328
+ ]
329
+ };
330
+ }
331
+ } else if (role === 'Active') {
332
+ if (counts.active >= 3 && !change.replaces_existing) {
333
+ return {
334
+ allowed: false,
335
+ reason: `Protocol violation: Max 3 Active Slots permitted. Your Core Stack is congested.`,
336
+ alternatives: [
337
+ `Cluster ${change.tool_name} into an existing Active slot (e.g., as a supporting tool in a sub-stack)`,
338
+ "Archive least-used Active node",
339
+ `Move ${change.tool_name} to Supporting tier`
340
+ ]
341
+ };
342
+ }
343
+ } else if (role === 'Supporting') {
344
+ if (counts.supporting >= 5 && !change.replaces_existing) {
345
+ return {
346
+ allowed: false,
347
+ reason: `Protocol violation: Max 5 Supporting Slots permitted in the Core Stack.`,
348
+ alternatives: [
349
+ `Nest ${change.tool_name} inside an existing Supporting sub-stack`,
350
+ "Archive least-used Supporting node",
351
+ "Promote this to Active if critical (requires archiving an Active slot)"
352
+ ]
353
+ };
354
+ }
355
+ }
356
+ }
357
+
358
+ return { allowed: true };
359
+ }
360
+
361
+ private static enforceMaturityGates(state: MaturityState, change: ProposedChange) {
362
+ const GATES: Record<number, any> = {
363
+ 1: {
364
+ level_name: "Fragmented",
365
+ min_stability_days: 7, // Stability required to REACH Level 2
366
+ allowed_changes: ["remove_tool", "audit", "emergency_subtract"],
367
+ blocked_changes: ["add_tool", "change_anchor"],
368
+ definition: "Tools and processes are random, chaotic, and uncoordinated.",
369
+ primary_action: "Audit & Eliminate. Reduce tool count by 30%.",
370
+ message: "Level 1: Focus on subtraction and stabilization only"
371
+ },
372
+ 2: {
373
+ level_name: "Siloed",
374
+ min_stability_days: 14, // Stability required to REACH Level 3
375
+ allowed_changes: ["remove_tool", "audit", "change_role"],
376
+ blocked_changes: ["add_tool", "change_anchor"],
377
+ definition: "Structure exists, but systems operate in isolation.",
378
+ primary_action: "Standardize. Create specific 'Anchors' for each workflow.",
379
+ message: "Level 2: Maintain 14 days stability before additions"
380
+ },
381
+ 3: {
382
+ level_name: "Integrated",
383
+ min_stability_days: 30, // Stability required to REACH Level 4
384
+ allowed_changes: ["remove_tool", "audit", "add_tool", "change_role"],
385
+ blocked_changes: ["change_anchor"],
386
+ definition: "Data flows between systems; reduced friction.",
387
+ primary_action: "Automate. Use APIs to connect Edges.",
388
+ message: "Level 3: Can adjust Active/Supporting after 30 days stability"
389
+ },
390
+ 4: {
391
+ level_name: "Aligned",
392
+ min_stability_days: 90, // Stability required to REACH Level 5
393
+ allowed_changes: ["remove_tool", "audit", "add_tool", "change_role", "change_anchor"],
394
+ blocked_changes: [],
395
+ definition: "Stack reflects values, strategy, and purpose.",
396
+ primary_action: "Refine. Align rituals with tool usage.",
397
+ message: "Level 4: All changes permitted with 90+ days stability"
398
+ },
399
+ 5: {
400
+ level_name: "Resonant",
401
+ min_stability_days: 180,
402
+ allowed_changes: ["all"],
403
+ blocked_changes: [],
404
+ definition: "Tech amplifies unique human value and signal.",
405
+ primary_action: "Transcend. The stack becomes invisible.",
406
+ message: "Level 5: Mature stack, trust your judgment"
407
+ }
408
+ };
409
+
410
+ const gate = GATES[state.level];
411
+
412
+ // Update state with metadata if missing
413
+ if (!state.level_name || state.level_name !== gate.level_name) {
414
+ state.level_name = gate.level_name;
415
+ state.definition = gate.definition;
416
+ state.primary_action = gate.primary_action;
417
+ }
418
+
419
+ // Action check (Subtraction is ALWAYS allowed regardless of stability)
420
+ if (change.type === 'remove_tool' || change.type === 'audit') {
421
+ return { allowed: true };
422
+ }
423
+
424
+ // Stability check for ADDITIONS/CHANGES
425
+ // Rules are based on the NEXT gate. If we are L2, we are subject to the L2 "maintenance" rules.
426
+ const currentStability = state.stability_days;
427
+
428
+ // Block additions if current level stability requirement isn't met or action is generally blocked
429
+ if (gate.blocked_changes.includes(change.type)) {
430
+ return {
431
+ allowed: false,
432
+ reason: `${gate.message}. Action '${change.type}' is unauthorized at the ${gate.level_name} stage.`,
433
+ gate_requirements: gate
434
+ };
435
+ }
436
+
437
+ // Special rule: Stability threshold for any "positive" change (adding/moving)
438
+ const isExpansion = change.type === 'add_tool' || change.type === 'change_role' || change.type === 'change_anchor';
439
+ const prevGateStability = state.level > 1 ? GATES[state.level - 1].min_stability_days : 0;
440
+
441
+ if (currentStability < prevGateStability && isExpansion) {
442
+ return {
443
+ allowed: false,
444
+ reason: `Stability gate: Reach ${prevGateStability} days of stability in the ${gate.level_name} stage before expanding. Current: ${currentStability} days.`,
445
+ gate_requirements: {
446
+ required_days: prevGateStability,
447
+ current_days: currentStability
448
+ }
449
+ };
450
+ }
451
+
452
+ return { allowed: true };
453
+ }
454
+
455
+ static getGovernanceContext(): GovernanceContext {
456
+ const tools = this.getStack();
457
+ const state = this.getMaturityState();
458
+
459
+ // Group into Functional Nodes for the context
460
+ const nodeMap: Record<string, { role: string, tools: string[] }> = {};
461
+ const unclassified: any[] = [];
462
+
463
+ tools.forEach(t => {
464
+ if (t.functionId) {
465
+ if (!nodeMap[t.functionId]) nodeMap[t.functionId] = { role: t.role, tools: [] };
466
+ nodeMap[t.functionId].tools.push(t.name);
467
+ } else {
468
+ unclassified.push({ id: t.name, role: t.role, tools: [t.name] });
469
+ }
470
+ });
471
+
472
+ const functionalNodes = [
473
+ ...Object.entries(nodeMap).map(([id, data]) => ({ id, ...data })),
474
+ ...unclassified
475
+ ];
476
+
477
+ // Determine allowed/blocked actions for UI/Context
478
+ const allActions: Array<'add_tool' | 'remove_tool' | 'change_role' | 'change_anchor'> = ["add_tool", "remove_tool", "change_role", "change_anchor"];
479
+ const blocked = allActions.filter(a => {
480
+ const res = this.validateStackChange({ type: a, tool_name: '' });
481
+ return !res.allowed;
482
+ });
483
+ const allowed = allActions.filter(a => !blocked.includes(a));
484
+
485
+ // Progression check
486
+ const nextLevel = state.level < 5 ? state.level + 1 : null;
487
+ const canLevelUp = nextLevel && state.stability_days >= this.getNextGateRequiredDays(state.level);
488
+ const csiDelta = (state.csi_latest || 0) - (state.csi_baseline || state.csi_latest || 0);
489
+
490
+ return {
491
+ current_stack: {
492
+ anchor: tools.find(t => t.role === 'Anchor') || null,
493
+ active: tools.filter(t => t.role === 'Active'),
494
+ supporting: tools.filter(t => t.role === 'Supporting')
495
+ },
496
+ functional_nodes: functionalNodes,
497
+ maturity_level: state.level,
498
+ maturity_name: state.level_name || "Unknown",
499
+ stability_days: state.stability_days,
500
+ csi_latest: state.csi_latest || 0,
501
+ allowed_actions: allowed,
502
+ blocked_actions: blocked, progression: {
503
+ can_level_up: !!canLevelUp,
504
+ next_level: nextLevel,
505
+ days_remaining: Math.max(0, this.getNextGateRequiredDays(state.level) - state.stability_days),
506
+ csi_delta: csiDelta,
507
+ is_l2_eligible: csiDelta >= 10
508
+ }
509
+ };
510
+ }
511
+
512
+ private static getNextGateRequiredDays(level: number): number {
513
+ const GATES_DAYS: Record<number, number> = {
514
+ 1: 7,
515
+ 2: 14,
516
+ 3: 30,
517
+ 4: 90,
518
+ 5: 180
519
+ };
520
+ return GATES_DAYS[level] || 0;
521
+ }
522
+ }
@@ -0,0 +1,138 @@
1
+ import { ToolInstance } from "./531-rule.js";
2
+ import { MethodologyLoader, BaguaCategory, InnerDiamondCategory } from "./methodology.js";
3
+
4
+ /**
5
+ * LifeAreaAnalysis: The result of mapping a stack to life areas.
6
+ */
7
+ export interface LifeAreaAnalysis {
8
+ areas: {
9
+ id: string;
10
+ label: string;
11
+ tools: string[];
12
+ description: string;
13
+ }[];
14
+ gaps: string[];
15
+ overIndexed: string[];
16
+ }
17
+
18
+ /**
19
+ * InnerDiamondAnalysis: The result of mapping a stack to deep identity patterns (L3).
20
+ */
21
+ export interface InnerDiamondAnalysis {
22
+ reflections: {
23
+ id: string;
24
+ label: string;
25
+ observation: string;
26
+ prompt: string;
27
+ }[];
28
+ forecast: {
29
+ sovereignty_score: number;
30
+ primary_risk: string;
31
+ evolution_path: string;
32
+ };
33
+ }
34
+
35
+ /**
36
+ * LifeAreaMapper: Interface for mapping tools to life areas/domains.
37
+ */
38
+ export interface LifeAreaMapper {
39
+ mapToolsToAreas(tools: ToolInstance[], practitionerMode?: boolean): LifeAreaAnalysis;
40
+ }
41
+
42
+ /**
43
+ * BaguaMapper: The default implementation using the 9-room Bagua system.
44
+ */
45
+ export class BaguaMapper implements LifeAreaMapper {
46
+ private categories: BaguaCategory[];
47
+
48
+ constructor() {
49
+ this.categories = MethodologyLoader.loadBaguaCategories();
50
+ }
51
+
52
+ /**
53
+ * Maps tools to Bagua rooms and returns sanitized labels.
54
+ */
55
+ mapToolsToAreas(tools: ToolInstance[], practitionerMode: boolean = false): LifeAreaAnalysis {
56
+ const mapping = this.categories.map(cat => ({
57
+ id: cat.name, // Internal ID (e.g., Li, Kun)
58
+ label: practitionerMode ? cat.name : (cat.userFacingLabel || cat.description),
59
+ tools: tools.filter(t => t.functionId === cat.name).map(t => t.name),
60
+ description: cat.description
61
+ }));
62
+
63
+ const gaps = mapping.filter(m => m.tools.length === 0).map(m => m.label);
64
+ const overIndexed = mapping.filter(m => m.tools.length > 2).map(m => m.label);
65
+
66
+ return {
67
+ areas: mapping,
68
+ gaps,
69
+ overIndexed
70
+ };
71
+ }
72
+ }
73
+
74
+ /**
75
+ * DiamondMapper: L3 Identity and Purpose mapping.
76
+ */
77
+ export class DiamondMapper {
78
+ private categories: InnerDiamondCategory[];
79
+
80
+ constructor() {
81
+ this.categories = MethodologyLoader.loadInnerDiamondCategories();
82
+ }
83
+
84
+ /**
85
+ * Generates L3 reflection points based on the tool stack.
86
+ */
87
+ mapToDiamond(tools: ToolInstance[], practitionerMode: boolean = false): InnerDiamondAnalysis {
88
+ // Logic for L3 is more qualitative and pattern-based
89
+ const prompts = MethodologyLoader.loadConsentPrompts(); // Not exactly what we need, but we can have specific prompts
90
+
91
+ const reflections = this.categories.map(cat => ({
92
+ id: cat.name,
93
+ label: practitionerMode ? cat.name : (cat.userFacingLabel || cat.name),
94
+ observation: this.getObservationForCategory(cat.name, tools),
95
+ prompt: this.getPromptForCategory(cat.name, tools)
96
+ }));
97
+
98
+ // Calculate a proxy sovereignty score based on variety of functions and tool count
99
+ const uniqueFunctions = new Set(tools.map(t => t.functionId).filter(Boolean)).size;
100
+ const sovScore = Math.min(100, Math.round((uniqueFunctions / 9) * 100));
101
+
102
+ return {
103
+ reflections,
104
+ forecast: {
105
+ sovereignty_score: sovScore,
106
+ primary_risk: tools.length > 9 ? "Conscious Fragmentation" : "Dependency Lock-in",
107
+ evolution_path: "Move from 'tool-centric' to 'process-centric' autonomy."
108
+ }
109
+ };
110
+ }
111
+
112
+ private getObservationForCategory(cat: string, tools: ToolInstance[]): string {
113
+ switch (cat) {
114
+ case 'Identity':
115
+ return tools.length > 0 ? `Your choices in ${tools[0].name} suggest a focus on efficiency.` : "No clear identity pattern detected.";
116
+ case 'Purpose':
117
+ const anchors = tools.filter(t => t.role === 'Anchor');
118
+ return anchors.length > 0 ? `Your Anchor (${anchors[0].name}) is the seat of your daily purpose.` : "Your purpose lacks a central digital anchor.";
119
+ case 'Sovereignty':
120
+ return `You are currently balancing ${tools.length} nodes of external dependencies.`;
121
+ default:
122
+ return "Reflecting on pattern...";
123
+ }
124
+ }
125
+
126
+ private getPromptForCategory(cat: string, tools: ToolInstance[]): string {
127
+ switch (cat) {
128
+ case 'Identity':
129
+ return "Who would you be if this stack was reset tomorrow?";
130
+ case 'Purpose':
131
+ return "Does this stack serve your mission, or does it define it?";
132
+ case 'Sovereignty':
133
+ return "Where are you choosing not to see a dependency?";
134
+ default:
135
+ return "What is ready to evolve?";
136
+ }
137
+ }
138
+ }